diff options
Diffstat (limited to 'src/mac.m')
-rw-r--r-- | src/mac.m | 1726 |
1 files changed, 869 insertions, 857 deletions
@@ -40,85 +40,85 @@ typedef NSUInteger NSWindowStyleMask; static NSRect rectToScreen(NSScreen* screen, NSRect rect) { - const double screenHeight = [screen frame].size.height; + const double screenHeight = [screen frame].size.height; - rect.origin.y = screenHeight - rect.origin.y - rect.size.height; - return rect; + rect.origin.y = screenHeight - rect.origin.y - rect.size.height; + return rect; } static NSScreen* viewScreen(PuglView* view) { - return view->impl->window ? [view->impl->window screen] : [NSScreen mainScreen]; + return view->impl->window ? [view->impl->window screen] + : [NSScreen mainScreen]; } static NSRect nsRectToPoints(PuglView* view, const NSRect rect) { - const double scaleFactor = [viewScreen(view) backingScaleFactor]; + const double scaleFactor = [viewScreen(view) backingScaleFactor]; - return NSMakeRect(rect.origin.x / scaleFactor, - rect.origin.y / scaleFactor, - rect.size.width / scaleFactor, - rect.size.height / scaleFactor); + return NSMakeRect(rect.origin.x / scaleFactor, + rect.origin.y / scaleFactor, + rect.size.width / scaleFactor, + rect.size.height / scaleFactor); } static NSRect nsRectFromPoints(PuglView* view, const NSRect rect) { - const double scaleFactor = [viewScreen(view) backingScaleFactor]; + const double scaleFactor = [viewScreen(view) backingScaleFactor]; - return NSMakeRect(rect.origin.x * scaleFactor, - rect.origin.y * scaleFactor, - rect.size.width * scaleFactor, - rect.size.height * scaleFactor); + return NSMakeRect(rect.origin.x * scaleFactor, + rect.origin.y * scaleFactor, + rect.size.width * scaleFactor, + rect.size.height * scaleFactor); } static NSPoint nsPointFromPoints(PuglView* view, const NSPoint point) { - const double scaleFactor = [viewScreen(view) backingScaleFactor]; + const double scaleFactor = [viewScreen(view) backingScaleFactor]; - return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor); + return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor); } static NSRect rectToNsRect(const PuglRect rect) { - return NSMakeRect(rect.x, rect.y, rect.width, rect.height); + return NSMakeRect(rect.x, rect.y, rect.width, rect.height); } static NSSize sizePoints(PuglView* view, const double width, const double height) { - const double scaleFactor = [viewScreen(view) backingScaleFactor]; + const double scaleFactor = [viewScreen(view) backingScaleFactor]; - return NSMakeSize(width / scaleFactor, height / scaleFactor); + return NSMakeSize(width / scaleFactor, height / scaleFactor); } static void updateViewRect(PuglView* view) { - NSWindow* const window = view->impl->window; - if (window) { - const NSRect screenFramePt = [[NSScreen mainScreen] frame]; - const NSRect screenFramePx = nsRectFromPoints(view, screenFramePt); - const NSRect framePt = [window frame]; - const NSRect contentPt = [window contentRectForFrameRect:framePt]; - const NSRect contentPx = nsRectFromPoints(view, contentPt); - const double screenHeight = screenFramePx.size.height; + NSWindow* const window = view->impl->window; + if (window) { + const NSRect screenFramePt = [[NSScreen mainScreen] frame]; + const NSRect screenFramePx = nsRectFromPoints(view, screenFramePt); + const NSRect framePt = [window frame]; + const NSRect contentPt = [window contentRectForFrameRect:framePt]; + const NSRect contentPx = nsRectFromPoints(view, contentPt); + const double screenHeight = screenFramePx.size.height; - view->frame.x = contentPx.origin.x; - view->frame.y = screenHeight - contentPx.origin.y - contentPx.size.height; - view->frame.width = contentPx.size.width; - view->frame.height = contentPx.size.height; - } + view->frame.x = contentPx.origin.x; + view->frame.y = screenHeight - contentPx.origin.y - contentPx.size.height; + view->frame.width = contentPx.size.width; + view->frame.height = contentPx.size.height; + } } -@implementation PuglWindow -{ +@implementation PuglWindow { @public - PuglView* puglview; + PuglView* puglview; } - (id)initWithContentRect:(NSRect)contentRect @@ -126,617 +126,638 @@ updateViewRect(PuglView* view) backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag { - (void)flag; + (void)flag; - NSWindow* result = [super initWithContentRect:contentRect - styleMask:aStyle - backing:bufferingType - defer:NO]; + NSWindow* result = [super initWithContentRect:contentRect + styleMask:aStyle + backing:bufferingType + defer:NO]; - [result setAcceptsMouseMovedEvents:YES]; - return (PuglWindow*)result; + [result setAcceptsMouseMovedEvents:YES]; + return (PuglWindow*)result; } - (void)setPuglview:(PuglView*)view { - puglview = view; + puglview = view; - [self - setContentSize:sizePoints(view, view->frame.width, view->frame.height)]; + [self setContentSize:sizePoints(view, view->frame.width, view->frame.height)]; } - (BOOL)canBecomeKeyWindow { - return YES; + return YES; } - (BOOL)canBecomeMainWindow { - return YES; + return YES; } - (void)setIsVisible:(BOOL)flag { - if (flag && !puglview->visible) { - const PuglEventConfigure ev = { - PUGL_CONFIGURE, - 0, - puglview->frame.x, - puglview->frame.y, - puglview->frame.width, - puglview->frame.height, - }; + if (flag && !puglview->visible) { + const PuglEventConfigure ev = { + PUGL_CONFIGURE, + 0, + puglview->frame.x, + puglview->frame.y, + puglview->frame.width, + puglview->frame.height, + }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); - puglDispatchSimpleEvent(puglview, PUGL_MAP); - } else if (!flag && puglview->visible) { - puglDispatchSimpleEvent(puglview, PUGL_UNMAP); - } + puglDispatchEvent(puglview, (const PuglEvent*)&ev); + puglDispatchSimpleEvent(puglview, PUGL_MAP); + } else if (!flag && puglview->visible) { + puglDispatchSimpleEvent(puglview, PUGL_UNMAP); + } - puglview->visible = flag; + puglview->visible = flag; - [super setIsVisible:flag]; + [super setIsVisible:flag]; } @end -@implementation PuglWrapperView -{ +@implementation PuglWrapperView { @public - PuglView* puglview; - NSTrackingArea* trackingArea; - NSMutableAttributedString* markedText; - NSMutableDictionary* userTimers; - bool reshaped; + PuglView* puglview; + NSTrackingArea* trackingArea; + NSMutableAttributedString* markedText; + NSMutableDictionary* userTimers; + bool reshaped; } - (void)dispatchExpose:(NSRect)rect { - const double scaleFactor = [[NSScreen mainScreen] backingScaleFactor]; + const double scaleFactor = [[NSScreen mainScreen] backingScaleFactor]; - if (reshaped) { - updateViewRect(puglview); + if (reshaped) { + updateViewRect(puglview); - const PuglEventConfigure ev = { - PUGL_CONFIGURE, - 0, - puglview->frame.x, - puglview->frame.y, - puglview->frame.width, - puglview->frame.height, - }; + const PuglEventConfigure ev = { + PUGL_CONFIGURE, + 0, + puglview->frame.x, + puglview->frame.y, + puglview->frame.width, + puglview->frame.height, + }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); - reshaped = false; - } + puglDispatchEvent(puglview, (const PuglEvent*)&ev); + reshaped = false; + } - if (![[puglview->impl->drawView window] isVisible]) { - return; - } + if (![[puglview->impl->drawView window] isVisible]) { + return; + } - const PuglEventExpose ev = { - PUGL_EXPOSE, - 0, - rect.origin.x * scaleFactor, - rect.origin.y * scaleFactor, - rect.size.width * scaleFactor, - rect.size.height * scaleFactor, - }; + const PuglEventExpose ev = { + PUGL_EXPOSE, + 0, + rect.origin.x * scaleFactor, + rect.origin.y * scaleFactor, + rect.size.width * scaleFactor, + rect.size.height * scaleFactor, + }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); + puglDispatchEvent(puglview, (const PuglEvent*)&ev); } - (NSSize)intrinsicContentSize { - if (puglview->defaultWidth || puglview->defaultHeight) { - return sizePoints(puglview, - puglview->defaultWidth, - puglview->defaultHeight); - } + if (puglview->defaultWidth || puglview->defaultHeight) { + return sizePoints( + puglview, puglview->defaultWidth, puglview->defaultHeight); + } - return NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); + return NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); } - (BOOL)isFlipped { - return YES; + return YES; } - (BOOL)acceptsFirstResponder { - return YES; + return YES; } - (void)setReshaped { - reshaped = true; + reshaped = true; } static uint32_t getModifiers(const NSEvent* const ev) { - const NSEventModifierFlags modifierFlags = [ev modifierFlags]; + 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)); + 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; + 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]; - } + 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]; + 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 nsPointFromPoints(puglview, - [self convertPoint:[event locationInWindow] - fromView:nil]); + return nsPointFromPoints( + puglview, [self convertPoint:[event locationInWindow] fromView:nil]); } static void handleCrossing(PuglWrapperView* 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, - }; + 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); + puglDispatchEvent(view->puglview, (const PuglEvent*)&ev); } - (void)mouseEntered:(NSEvent*)event { - handleCrossing(self, event, PUGL_POINTER_IN); - [puglview->impl->cursor set]; - puglview->impl->mouseTracked = true; + handleCrossing(self, event, PUGL_POINTER_IN); + [puglview->impl->cursor set]; + puglview->impl->mouseTracked = true; } - (void)mouseExited:(NSEvent*)event { - [[NSCursor arrowCursor] set]; - handleCrossing(self, event, PUGL_POINTER_OUT); - puglview->impl->mouseTracked = false; + [[NSCursor arrowCursor] set]; + handleCrossing(self, event, PUGL_POINTER_OUT); + puglview->impl->mouseTracked = false; } - (void)cursorUpdate:(NSEvent*)event { - (void)event; - [puglview->impl->cursor set]; + (void)event; + [puglview->impl->cursor set]; } - (void)mouseMoved:(NSEvent*)event { - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglEventMotion ev = { - PUGL_MOTION, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - }; + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const PuglEventMotion ev = { + PUGL_MOTION, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); + puglDispatchEvent(puglview, (const PuglEvent*)&ev); } - (void)mouseDragged:(NSEvent*)event { - [self mouseMoved: event]; + [self mouseMoved:event]; } - (void)rightMouseDragged:(NSEvent*)event { - [self mouseMoved: event]; + [self mouseMoved:event]; } - (void)otherMouseDragged:(NSEvent*)event { - [self mouseMoved: 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, - }; + 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); + 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, - }; + 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); + puglDispatchEvent(puglview, (const PuglEvent*)&ev); } - (void)rightMouseDown:(NSEvent*)event { - [self mouseDown: event]; + [self mouseDown:event]; } - (void)rightMouseUp:(NSEvent*)event { - [self mouseUp: event]; + [self mouseUp:event]; } - (void)otherMouseDown:(NSEvent*)event { - [self mouseDown: event]; + [self mouseDown:event]; } - (void)otherMouseUp:(NSEvent*)event { - [self mouseUp: event]; + [self mouseUp:event]; } - (void)scrollWheel:(NSEvent*)event { - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const double dx = [event scrollingDeltaX]; - const double dy = [event scrollingDeltaY]; - const PuglScrollDirection dir = - ((dx == 0.0 && dy > 0.0) - ? PUGL_SCROLL_UP - : ((dx == 0.0 && dy < 0.0) - ? PUGL_SCROLL_DOWN - : ((dy == 0.0 && dx > 0.0) - ? PUGL_SCROLL_RIGHT - : ((dy == 0.0 && dx < 0.0) ? PUGL_SCROLL_LEFT - : PUGL_SCROLL_SMOOTH)))); - - const PuglEventScroll ev = { - PUGL_SCROLL, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir, - dx, - dy, - }; - - puglDispatchEvent(puglview, (const PuglEvent*)&ev); + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const double dx = [event scrollingDeltaX]; + const double dy = [event scrollingDeltaY]; + const PuglScrollDirection dir = + ((dx == 0.0 && dy > 0.0) + ? PUGL_SCROLL_UP + : ((dx == 0.0 && dy < 0.0) + ? PUGL_SCROLL_DOWN + : ((dy == 0.0 && dx > 0.0) + ? PUGL_SCROLL_RIGHT + : ((dy == 0.0 && dx < 0.0) ? PUGL_SCROLL_LEFT + : PUGL_SCROLL_SMOOTH)))); + + const PuglEventScroll ev = { + PUGL_SCROLL, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir, + dx, + dy, + }; + + puglDispatchEvent(puglview, (const PuglEvent*)&ev); } - (void)keyDown:(NSEvent*)event { - if (puglview->hints[PUGL_IGNORE_KEY_REPEAT] && [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]]; - } + if (puglview->hints[PUGL_IGNORE_KEY_REPEAT] && [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); + 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; + return [markedText length] > 0; } - (NSRange)markedRange { - return (([markedText length] > 0) - ? NSMakeRange(0, [markedText length] - 1) - : NSMakeRange(NSNotFound, 0)); + return (([markedText length] > 0) ? NSMakeRange(0, [markedText length] - 1) + : NSMakeRange(NSNotFound, 0)); } - (NSRange)selectedRange { - return NSMakeRange(NSNotFound, 0); + return NSMakeRange(NSNotFound, 0); } - (void)setMarkedText:(id)string selectedRange:(NSRange)selected replacementRange:(NSRange)replacement { - (void)selected; - (void)replacement; - [markedText release]; - markedText = ( - [(NSObject*)string isKindOfClass:[NSAttributedString class]] - ? [[NSMutableAttributedString alloc] initWithAttributedString:string] - : [[NSMutableAttributedString alloc] initWithString:string]); + (void)selected; + (void)replacement; + [markedText release]; + markedText = + ([(NSObject*)string isKindOfClass:[NSAttributedString class]] + ? [[NSMutableAttributedString alloc] initWithAttributedString:string] + : [[NSMutableAttributedString alloc] initWithString:string]); } - (void)unmarkText { - [[markedText mutableString] setString:@""]; + [[markedText mutableString] setString:@""]; } - (NSArray*)validAttributesForMarkedText { - return @[]; + return @[]; } - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range actualRange: - (NSRangePointer)actual + (NSRangePointer)actual { - (void)range; - (void)actual; - return nil; + (void)range; + (void)actual; + return nil; } - (NSUInteger)characterIndexForPoint:(NSPoint)point { - (void)point; - return 0; + (void)point; + return 0; } - (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actual { - (void)range; - (void)actual; + (void)range; + (void)actual; - const NSRect frame = [self bounds]; - return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0); + const NSRect frame = [self bounds]; + return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0); } - (void)doCommandBySelector:(SEL)selector { - (void)selector; + (void)selector; } - (void)insertText:(id)string replacementRange:(NSRange)replacement { - (void)replacement; - - NSEvent* const event = [NSApp currentEvent]; - NSString* const characters = - ([(NSObject*)string isKindOfClass:[NSAttributedString class]] - ? [(NSAttributedString*)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)replacement; + + NSEvent* const event = [NSApp currentEvent]; + NSString* const characters = + ([(NSObject*)string isKindOfClass:[NSAttributedString class]] + ? [(NSAttributedString*)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 = (PuglKey)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; + const uint32_t mods = getModifiers(event); + PuglEventType type = PUGL_NOTHING; + PuglKey special = (PuglKey)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; + return NO; } - (void)viewWillStartLiveResize { - puglDispatchSimpleEvent(puglview, PUGL_LOOP_ENTER); + puglDispatchSimpleEvent(puglview, PUGL_LOOP_ENTER); } - (void)viewWillDraw { - puglDispatchSimpleEvent(puglview, PUGL_UPDATE); - [super viewWillDraw]; + puglDispatchSimpleEvent(puglview, PUGL_UPDATE); + [super viewWillDraw]; } - (void)resizeTick { - puglPostRedisplay(puglview); + puglPostRedisplay(puglview); } - (void)timerTick:(NSTimer*)userTimer { - const NSNumber* userInfo = userTimer.userInfo; - const PuglEventTimer ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue}; + const NSNumber* userInfo = userTimer.userInfo; + const PuglEventTimer ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue}; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); + puglDispatchEvent(puglview, (const PuglEvent*)&ev); } - (void)viewDidEndLiveResize { - puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE); + puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE); } @end @@ -747,51 +768,50 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) @end -@implementation PuglWindowDelegate -{ - PuglWindow* window; +@implementation PuglWindowDelegate { + PuglWindow* window; } - (instancetype)initWithPuglWindow:(PuglWindow*)puglWindow { - if ((self = [super init])) { - window = puglWindow; - } + if ((self = [super init])) { + window = puglWindow; + } - return self; + return self; } - (BOOL)windowShouldClose:(id)sender { - (void)sender; + (void)sender; - puglDispatchSimpleEvent(window->puglview, PUGL_CLOSE); - return YES; + puglDispatchSimpleEvent(window->puglview, PUGL_CLOSE); + return YES; } - (void)windowDidMove:(NSNotification*)notification { - (void)notification; + (void)notification; - updateViewRect(window->puglview); + updateViewRect(window->puglview); } - (void)windowDidBecomeKey:(NSNotification*)notification { - (void)notification; + (void)notification; - PuglEvent ev = {{PUGL_FOCUS_IN, 0}}; - ev.focus.mode = PUGL_CROSSING_NORMAL; - puglDispatchEvent(window->puglview, &ev); + PuglEvent ev = {{PUGL_FOCUS_IN, 0}}; + ev.focus.mode = PUGL_CROSSING_NORMAL; + puglDispatchEvent(window->puglview, &ev); } - (void)windowDidResignKey:(NSNotification*)notification { - (void)notification; + (void)notification; - PuglEvent ev = {{PUGL_FOCUS_OUT, 0}}; - ev.focus.mode = PUGL_CROSSING_NORMAL; - puglDispatchEvent(window->puglview, &ev); + PuglEvent ev = {{PUGL_FOCUS_OUT, 0}}; + ev.focus.mode = PUGL_CROSSING_NORMAL; + puglDispatchEvent(window->puglview, &ev); } @end @@ -799,532 +819,526 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) PuglWorldInternals* puglInitWorldInternals(PuglWorldType type, PuglWorldFlags PUGL_UNUSED(flags)) { - PuglWorldInternals* impl = (PuglWorldInternals*)calloc( - 1, sizeof(PuglWorldInternals)); + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); - impl->app = [NSApplication sharedApplication]; + impl->app = [NSApplication sharedApplication]; - if (type == PUGL_PROGRAM) { - impl->autoreleasePool = [NSAutoreleasePool new]; - } + if (type == PUGL_PROGRAM) { + impl->autoreleasePool = [NSAutoreleasePool new]; + } - return impl; + return impl; } void puglFreeWorldInternals(PuglWorld* world) { - if (world->impl->autoreleasePool) { - [world->impl->autoreleasePool drain]; - } + if (world->impl->autoreleasePool) { + [world->impl->autoreleasePool drain]; + } - free(world->impl); + free(world->impl); } void* puglGetNativeWorld(PuglWorld* PUGL_UNUSED(world)) { - return NULL; + return NULL; } PuglInternals* puglInitViewInternals(void) { - PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); - impl->cursor = [NSCursor arrowCursor]; + impl->cursor = [NSCursor arrowCursor]; - return impl; + return impl; } 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: (CGFloat)constant]; + return + [NSLayoutConstraint constraintWithItem:item + attribute:attribute + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:(CGFloat)constant]; } PuglStatus puglRealize(PuglView* view) { - PuglInternals* impl = view->impl; - if (impl->wrapperView) { - return PUGL_FAILURE; - } - - const NSScreen* const screen = [NSScreen mainScreen]; - const double scaleFactor = [screen backingScaleFactor]; - - // Getting depth from the display mode seems tedious, just set usual values - if (view->hints[PUGL_RED_BITS] == PUGL_DONT_CARE) { - view->hints[PUGL_RED_BITS] = 8; - } - if (view->hints[PUGL_BLUE_BITS] == PUGL_DONT_CARE) { - view->hints[PUGL_BLUE_BITS] = 8; - } - if (view->hints[PUGL_GREEN_BITS] == PUGL_DONT_CARE) { - view->hints[PUGL_GREEN_BITS] = 8; - } - if (view->hints[PUGL_ALPHA_BITS] == PUGL_DONT_CARE) { - view->hints[PUGL_ALPHA_BITS] = 8; - } - - CGDirectDisplayID displayId = CGMainDisplayID(); - CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); - - // Try to get refresh rate from mode (usually fails) - view->hints[PUGL_REFRESH_RATE] = (int)CGDisplayModeGetRefreshRate(mode); - - CGDisplayModeRelease(mode); - if (view->hints[PUGL_REFRESH_RATE] == 0) { - // Get refresh rate from a display link - // TODO: Keep and actually use the display link for something? - CVDisplayLinkRef link; - CVDisplayLinkCreateWithCGDisplay(displayId, &link); - - const CVTime p = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); - const double r = p.timeScale / (double)p.timeValue; - view->hints[PUGL_REFRESH_RATE] = (int)lrint(r); - - CVDisplayLinkRelease(link); - } - - if (view->frame.width == 0.0 && view->frame.height == 0.0) { - if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) { - return PUGL_BAD_CONFIGURATION; - } - - const double screenWidthPx = [screen frame].size.width * scaleFactor; - const double screenHeightPx = [screen frame].size.height * scaleFactor; - - view->frame.width = view->defaultWidth; - view->frame.height = view->defaultHeight; - view->frame.x = screenWidthPx / 2.0 - view->frame.width / 2.0; - view->frame.y = screenHeightPx / 2.0 - view->frame.height / 2.0; - } - - const NSRect framePx = rectToNsRect(view->frame); - const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor, - framePx.origin.y / scaleFactor, - framePx.size.width / scaleFactor, - framePx.size.height / scaleFactor); - - // Create wrapper view to handle input - impl->wrapperView = [PuglWrapperView alloc]; - impl->wrapperView->puglview = view; - impl->wrapperView->userTimers = [[NSMutableDictionary alloc] init]; - impl->wrapperView->markedText = [[NSMutableAttributedString alloc] init]; - [impl->wrapperView setAutoresizesSubviews:YES]; - [impl->wrapperView initWithFrame:framePt]; - [impl->wrapperView addConstraint: - puglConstraint(impl->wrapperView, NSLayoutAttributeWidth, view->minWidth)]; - [impl->wrapperView addConstraint: - puglConstraint(impl->wrapperView, NSLayoutAttributeHeight, view->minHeight)]; - - // Create draw view to be rendered to - PuglStatus st = PUGL_SUCCESS; - if ((st = view->backend->configure(view)) || - (st = view->backend->create(view))) { - return st; - } - - // Add draw view to wrapper view - [impl->wrapperView addSubview:impl->drawView]; - [impl->wrapperView setHidden:NO]; - [impl->drawView setHidden:NO]; - - if (view->parent) { - NSView* pview = (NSView*)view->parent; - [pview addSubview:impl->wrapperView]; - [impl->drawView setHidden:NO]; - [[impl->drawView window] makeFirstResponder:impl->wrapperView]; - } else { - unsigned style = (NSClosableWindowMask | - NSTitledWindowMask | - NSMiniaturizableWindowMask ); - if (view->hints[PUGL_RESIZABLE]) { - style |= NSResizableWindowMask; - } - - PuglWindow* window = [[[PuglWindow alloc] - initWithContentRect:rectToScreen([NSScreen mainScreen], framePt) - styleMask:style - backing:NSBackingStoreBuffered - defer:NO - ] retain]; - [window setPuglview:view]; - - if (view->title) { - NSString* titleString = [[NSString alloc] - initWithBytes:view->title - length:strlen(view->title) - encoding:NSUTF8StringEncoding]; - - [window setTitle:titleString]; - } - - if (view->minWidth || view->minHeight) { - [window setContentMinSize:sizePoints(view, - view->minWidth, - view->minHeight)]; - } - impl->window = window; - - ((NSWindow*)window).delegate = [[PuglWindowDelegate alloc] - initWithPuglWindow:window]; - - if (view->minAspectX && view->minAspectY) { - [window setContentAspectRatio:sizePoints(view, - view->minAspectX, - view->minAspectY)]; - } - - puglSetFrame(view, view->frame); - - [window setContentView:impl->wrapperView]; - [view->world->impl->app activateIgnoringOtherApps:YES]; - [window makeFirstResponder:impl->wrapperView]; - [window makeKeyAndOrderFront:window]; - [impl->window setIsVisible:NO]; - } - - [impl->wrapperView updateTrackingAreas]; - - puglDispatchSimpleEvent(view, PUGL_CREATE); - - return PUGL_SUCCESS; + PuglInternals* impl = view->impl; + if (impl->wrapperView) { + return PUGL_FAILURE; + } + + const NSScreen* const screen = [NSScreen mainScreen]; + const double scaleFactor = [screen backingScaleFactor]; + + // Getting depth from the display mode seems tedious, just set usual values + if (view->hints[PUGL_RED_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_RED_BITS] = 8; + } + if (view->hints[PUGL_BLUE_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_BLUE_BITS] = 8; + } + if (view->hints[PUGL_GREEN_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_GREEN_BITS] = 8; + } + if (view->hints[PUGL_ALPHA_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_ALPHA_BITS] = 8; + } + + CGDirectDisplayID displayId = CGMainDisplayID(); + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); + + // Try to get refresh rate from mode (usually fails) + view->hints[PUGL_REFRESH_RATE] = (int)CGDisplayModeGetRefreshRate(mode); + + CGDisplayModeRelease(mode); + if (view->hints[PUGL_REFRESH_RATE] == 0) { + // Get refresh rate from a display link + // TODO: Keep and actually use the display link for something? + CVDisplayLinkRef link; + CVDisplayLinkCreateWithCGDisplay(displayId, &link); + + const CVTime p = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); + const double r = p.timeScale / (double)p.timeValue; + view->hints[PUGL_REFRESH_RATE] = (int)lrint(r); + + CVDisplayLinkRelease(link); + } + + if (view->frame.width == 0.0 && view->frame.height == 0.0) { + if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) { + return PUGL_BAD_CONFIGURATION; + } + + const double screenWidthPx = [screen frame].size.width * scaleFactor; + const double screenHeightPx = [screen frame].size.height * scaleFactor; + + view->frame.width = view->defaultWidth; + view->frame.height = view->defaultHeight; + view->frame.x = screenWidthPx / 2.0 - view->frame.width / 2.0; + view->frame.y = screenHeightPx / 2.0 - view->frame.height / 2.0; + } + + const NSRect framePx = rectToNsRect(view->frame); + const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor, + framePx.origin.y / scaleFactor, + framePx.size.width / scaleFactor, + framePx.size.height / scaleFactor); + + // Create wrapper view to handle input + impl->wrapperView = [PuglWrapperView alloc]; + impl->wrapperView->puglview = view; + impl->wrapperView->userTimers = [[NSMutableDictionary alloc] init]; + impl->wrapperView->markedText = [[NSMutableAttributedString alloc] init]; + [impl->wrapperView setAutoresizesSubviews:YES]; + [impl->wrapperView initWithFrame:framePt]; + [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView, + NSLayoutAttributeWidth, + view->minWidth)]; + [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView, + NSLayoutAttributeHeight, + view->minHeight)]; + + // Create draw view to be rendered to + PuglStatus st = PUGL_SUCCESS; + if ((st = view->backend->configure(view)) || + (st = view->backend->create(view))) { + return st; + } + + // Add draw view to wrapper view + [impl->wrapperView addSubview:impl->drawView]; + [impl->wrapperView setHidden:NO]; + [impl->drawView setHidden:NO]; + + if (view->parent) { + NSView* pview = (NSView*)view->parent; + [pview addSubview:impl->wrapperView]; + [impl->drawView setHidden:NO]; + [[impl->drawView window] makeFirstResponder:impl->wrapperView]; + } else { + unsigned style = + (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask); + if (view->hints[PUGL_RESIZABLE]) { + style |= NSResizableWindowMask; + } + + PuglWindow* window = [[[PuglWindow alloc] + initWithContentRect:rectToScreen([NSScreen mainScreen], framePt) + styleMask:style + backing:NSBackingStoreBuffered + defer:NO] retain]; + [window setPuglview:view]; + + if (view->title) { + NSString* titleString = + [[NSString alloc] initWithBytes:view->title + length:strlen(view->title) + encoding:NSUTF8StringEncoding]; + + [window setTitle:titleString]; + } + + if (view->minWidth || view->minHeight) { + [window + setContentMinSize:sizePoints(view, view->minWidth, view->minHeight)]; + } + impl->window = window; + + ((NSWindow*)window).delegate = + [[PuglWindowDelegate alloc] initWithPuglWindow:window]; + + if (view->minAspectX && view->minAspectY) { + [window setContentAspectRatio:sizePoints(view, + view->minAspectX, + view->minAspectY)]; + } + + puglSetFrame(view, view->frame); + + [window setContentView:impl->wrapperView]; + [view->world->impl->app activateIgnoringOtherApps:YES]; + [window makeFirstResponder:impl->wrapperView]; + [window makeKeyAndOrderFront:window]; + [impl->window setIsVisible:NO]; + } + + [impl->wrapperView updateTrackingAreas]; + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + return PUGL_SUCCESS; } PuglStatus puglShow(PuglView* view) { - if (!view->impl->wrapperView) { - const PuglStatus st = puglRealize(view); - if (st) { - return st; - } - } + if (!view->impl->wrapperView) { + const PuglStatus st = puglRealize(view); + if (st) { + return st; + } + } - if (![view->impl->window isVisible]) { - [view->impl->window setIsVisible:YES]; - [view->impl->drawView setNeedsDisplay: YES]; - updateViewRect(view); - } + if (![view->impl->window isVisible]) { + [view->impl->window setIsVisible:YES]; + [view->impl->drawView setNeedsDisplay:YES]; + updateViewRect(view); + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus puglHide(PuglView* view) { - [view->impl->window setIsVisible:NO]; - return PUGL_SUCCESS; + [view->impl->window setIsVisible:NO]; + return PUGL_SUCCESS; } void puglFreeViewInternals(PuglView* view) { - if (view) { - if (view->backend) { - view->backend->destroy(view); - } - - if (view->impl) { - [view->impl->wrapperView removeFromSuperview]; - view->impl->wrapperView->puglview = NULL; - if (view->impl->window) { - [view->impl->window close]; - } - [view->impl->wrapperView release]; - if (view->impl->window) { - [view->impl->window release]; - } - free(view->impl); - } - } + if (view) { + if (view->backend) { + view->backend->destroy(view); + } + + if (view->impl) { + [view->impl->wrapperView removeFromSuperview]; + view->impl->wrapperView->puglview = NULL; + if (view->impl->window) { + [view->impl->window close]; + } + [view->impl->wrapperView release]; + if (view->impl->window) { + [view->impl->window release]; + } + free(view->impl); + } + } } PuglStatus puglGrabFocus(PuglView* view) { - NSWindow* window = [view->impl->wrapperView window]; + NSWindow* window = [view->impl->wrapperView window]; - [window makeKeyWindow]; - [window makeFirstResponder:view->impl->wrapperView]; - return PUGL_SUCCESS; + [window makeKeyWindow]; + [window makeFirstResponder:view->impl->wrapperView]; + return PUGL_SUCCESS; } bool puglHasFocus(const PuglView* view) { - PuglInternals* const impl = view->impl; + PuglInternals* const impl = view->impl; - return ([[impl->wrapperView window] isKeyWindow] && - [[impl->wrapperView window] firstResponder] == impl->wrapperView); + return ([[impl->wrapperView window] isKeyWindow] && + [[impl->wrapperView window] firstResponder] == impl->wrapperView); } PuglStatus puglRequestAttention(PuglView* view) { - if (![view->impl->window isKeyWindow]) { - [view->world->impl->app requestUserAttention:NSInformationalRequest]; - } + if (![view->impl->window isKeyWindow]) { + [view->world->impl->app requestUserAttention:NSInformationalRequest]; + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus puglStartTimer(PuglView* view, uintptr_t id, double timeout) { - puglStopTimer(view, id); + puglStopTimer(view, id); - NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id]; + NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id]; - NSTimer* timer = [NSTimer timerWithTimeInterval:timeout - target:view->impl->wrapperView - selector:@selector(timerTick:) - userInfo:idNumber - repeats:YES]; + NSTimer* timer = [NSTimer timerWithTimeInterval:timeout + target:view->impl->wrapperView + selector:@selector(timerTick:) + userInfo:idNumber + repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - view->impl->wrapperView->userTimers[idNumber] = timer; + view->impl->wrapperView->userTimers[idNumber] = timer; - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus puglStopTimer(PuglView* view, uintptr_t id) { - NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id]; - NSTimer* timer = view->impl->wrapperView->userTimers[idNumber]; + NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id]; + NSTimer* timer = view->impl->wrapperView->userTimers[idNumber]; - if (timer) { - [view->impl->wrapperView->userTimers removeObjectForKey:timer]; - [timer invalidate]; - return PUGL_SUCCESS; - } + if (timer) { + [view->impl->wrapperView->userTimers removeObjectForKey:timer]; + [timer invalidate]; + return PUGL_SUCCESS; + } - return PUGL_UNKNOWN_ERROR; + return PUGL_UNKNOWN_ERROR; } PuglStatus puglSendEvent(PuglView* view, const PuglEvent* event) { - if (event->type == PUGL_CLIENT) { - PuglWrapperView* wrapper = view->impl->wrapperView; - const NSWindow* window = [wrapper window]; - const NSRect rect = [wrapper frame]; - const NSPoint center = {NSMidX(rect), NSMidY(rect)}; - - NSEvent* nsevent = [NSEvent - otherEventWithType:NSApplicationDefined - location:center - modifierFlags:0 - timestamp:[[NSProcessInfo processInfo] systemUptime] - windowNumber:window.windowNumber - context:nil - subtype:PUGL_CLIENT - data1:(NSInteger)event->client.data1 - data2:(NSInteger)event->client.data2]; - - [view->world->impl->app postEvent:nsevent atStart:false]; - return PUGL_SUCCESS; - } + if (event->type == PUGL_CLIENT) { + PuglWrapperView* wrapper = view->impl->wrapperView; + const NSWindow* window = [wrapper window]; + const NSRect rect = [wrapper frame]; + const NSPoint center = {NSMidX(rect), NSMidY(rect)}; + + NSEvent* nsevent = + [NSEvent otherEventWithType:NSApplicationDefined + location:center + modifierFlags:0 + timestamp:[[NSProcessInfo processInfo] systemUptime] + windowNumber:window.windowNumber + context:nil + subtype:PUGL_CLIENT + data1:(NSInteger)event->client.data1 + data2:(NSInteger)event->client.data2]; - return PUGL_UNSUPPORTED_TYPE; + [view->world->impl->app postEvent:nsevent atStart:false]; + return PUGL_SUCCESS; + } + + return PUGL_UNSUPPORTED_TYPE; } #ifndef PUGL_DISABLE_DEPRECATED PuglStatus puglWaitForEvent(PuglView* view) { - return puglPollEvents(view->world, -1.0); + return puglPollEvents(view->world, -1.0); } #endif static void dispatchClientEvent(PuglWorld* world, NSEvent* ev) { - NSWindow* win = [ev window]; - NSPoint loc = [ev locationInWindow]; - for (size_t i = 0; i < world->numViews; ++i) { - PuglView* view = world->views[i]; - PuglWrapperView* wrapper = view->impl->wrapperView; - if ([wrapper window] == win && NSPointInRect(loc, [wrapper frame])) { - const PuglEventClient event = {PUGL_CLIENT, - 0, - (uintptr_t)[ev data1], - (uintptr_t)[ev data2]}; + NSWindow* win = [ev window]; + NSPoint loc = [ev locationInWindow]; + for (size_t i = 0; i < world->numViews; ++i) { + PuglView* view = world->views[i]; + PuglWrapperView* wrapper = view->impl->wrapperView; + if ([wrapper window] == win && NSPointInRect(loc, [wrapper frame])) { + const PuglEventClient event = { + PUGL_CLIENT, 0, (uintptr_t)[ev data1], (uintptr_t)[ev data2]}; - puglDispatchEvent(view, (const PuglEvent*)&event); - } - } + puglDispatchEvent(view, (const PuglEvent*)&event); + } + } } PuglStatus puglUpdate(PuglWorld* world, const double timeout) { - NSDate* date = ((timeout < 0) - ? [NSDate distantFuture] - : [NSDate dateWithTimeIntervalSinceNow:timeout]); - - for (NSEvent* ev = NULL; - (ev = [world->impl->app nextEventMatchingMask:NSAnyEventMask - untilDate:date - inMode:NSDefaultRunLoopMode - dequeue:YES]);) { - - if ([ev type] == NSApplicationDefined && [ev subtype] == PUGL_CLIENT) { - dispatchClientEvent(world, ev); - } + NSDate* date = + ((timeout < 0) ? [NSDate distantFuture] + : [NSDate dateWithTimeIntervalSinceNow:timeout]); + + for (NSEvent* ev = NULL; + (ev = [world->impl->app nextEventMatchingMask:NSAnyEventMask + untilDate:date + inMode:NSDefaultRunLoopMode + dequeue:YES]);) { + if ([ev type] == NSApplicationDefined && [ev subtype] == PUGL_CLIENT) { + dispatchClientEvent(world, ev); + } - [world->impl->app sendEvent: ev]; + [world->impl->app sendEvent:ev]; - if (timeout < 0) { - // Now that we've waited and got an event, set the date to now to - // avoid looping forever - date = [NSDate date]; - } - } + if (timeout < 0) { + // Now that we've waited and got an event, set the date to now to + // avoid looping forever + date = [NSDate date]; + } + } - for (size_t i = 0; i < world->numViews; ++i) { - PuglView* const view = world->views[i]; + for (size_t i = 0; i < world->numViews; ++i) { + PuglView* const view = world->views[i]; - if ([[view->impl->drawView window] isVisible]) { - puglDispatchSimpleEvent(view, PUGL_UPDATE); - } + if ([[view->impl->drawView window] isVisible]) { + puglDispatchSimpleEvent(view, PUGL_UPDATE); + } - [view->impl->drawView displayIfNeeded]; - } + [view->impl->drawView displayIfNeeded]; + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } #ifndef PUGL_DISABLE_DEPRECATED PuglStatus puglProcessEvents(PuglView* view) { - return puglDispatchEvents(view->world); + return puglDispatchEvents(view->world); } #endif double puglGetTime(const PuglWorld* world) { - return (mach_absolute_time() / 1e9) - world->startTime; + return (mach_absolute_time() / 1e9) - world->startTime; } PuglStatus puglPostRedisplay(PuglView* view) { - [view->impl->drawView setNeedsDisplay: YES]; - return PUGL_SUCCESS; + [view->impl->drawView setNeedsDisplay:YES]; + return PUGL_SUCCESS; } PuglStatus puglPostRedisplayRect(PuglView* view, const PuglRect rect) { - const NSRect rectPx = rectToNsRect(rect); + const NSRect rectPx = rectToNsRect(rect); - [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; + [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglNativeView puglGetNativeWindow(PuglView* view) { - return (PuglNativeView)view->impl->wrapperView; + return (PuglNativeView)view->impl->wrapperView; } PuglStatus puglSetWindowTitle(PuglView* view, const char* title) { - puglSetString(&view->title, title); + puglSetString(&view->title, title); - if (view->impl->window) { - NSString* titleString = [[NSString alloc] - initWithBytes:title - length:strlen(title) - encoding:NSUTF8StringEncoding]; + if (view->impl->window) { + NSString* titleString = + [[NSString alloc] initWithBytes:title + length:strlen(title) + encoding:NSUTF8StringEncoding]; - [view->impl->window setTitle:titleString]; - } + [view->impl->window setTitle:titleString]; + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus puglSetFrame(PuglView* view, const PuglRect frame) { - PuglInternals* const impl = view->impl; + PuglInternals* const impl = view->impl; - // Update view frame to exactly the requested frame in Pugl coordinates - view->frame = frame; + // Update view frame to exactly the requested frame in Pugl coordinates + view->frame = frame; - const NSRect framePx = rectToNsRect(frame); - const NSRect framePt = nsRectToPoints(view, framePx); - if (impl->window) { - // Resize window to fit new content rect - const NSRect screenPt = rectToScreen(viewScreen(view), framePt); - const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; + const NSRect framePx = rectToNsRect(frame); + const NSRect framePt = nsRectToPoints(view, framePx); + if (impl->window) { + // Resize window to fit new content rect + const NSRect screenPt = rectToScreen(viewScreen(view), framePt); + const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; - [impl->window setFrame:winFrame display:NO]; - } + [impl->window setFrame:winFrame display:NO]; + } - // Resize views - const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height); - const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; + // Resize views + const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height); + const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; - [impl->wrapperView setFrame:(impl->window ? sizePt : framePt)]; - [impl->drawView setFrame:sizePt]; + [impl->wrapperView setFrame:(impl->window ? sizePt : framePt)]; + [impl->drawView setFrame:sizePt]; - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus puglSetDefaultSize(PuglView* const view, const int width, const int height) { - view->defaultWidth = width; - view->defaultHeight = height; - return PUGL_SUCCESS; + view->defaultWidth = width; + view->defaultHeight = height; + return PUGL_SUCCESS; } PuglStatus puglSetMinSize(PuglView* const view, const int width, const int height) { - view->minWidth = width; - view->minHeight = height; + view->minWidth = width; + view->minHeight = height; - if (view->impl->window && (view->minWidth || view->minHeight)) { - [view->impl->window setContentMinSize:sizePoints(view, - view->minWidth, - view->minHeight)]; - } + if (view->impl->window && (view->minWidth || view->minHeight)) { + [view->impl->window + setContentMinSize:sizePoints(view, view->minWidth, view->minHeight)]; + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus puglSetMaxSize(PuglView* const view, const int width, const int height) { - view->maxWidth = width; - view->maxHeight = height; + view->maxWidth = width; + view->maxHeight = height; - if (view->impl->window && (view->maxWidth || view->maxHeight)) { - [view->impl->window setContentMaxSize:sizePoints(view, - view->maxWidth, - view->maxHeight)]; - } + if (view->impl->window && (view->maxWidth || view->maxHeight)) { + [view->impl->window + setContentMaxSize:sizePoints(view, view->maxWidth, view->maxHeight)]; + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus @@ -1334,35 +1348,34 @@ puglSetAspectRatio(PuglView* const view, const int maxX, const int maxY) { - view->minAspectX = minX; - view->minAspectY = minY; - view->maxAspectX = maxX; - view->maxAspectY = maxY; + view->minAspectX = minX; + view->minAspectY = minY; + view->maxAspectX = maxX; + view->maxAspectY = maxY; - if (view->impl->window && view->minAspectX && view->minAspectY) { - [view->impl->window setContentAspectRatio:sizePoints(view, - view->minAspectX, - view->minAspectY)]; - } + if (view->impl->window && view->minAspectX && view->minAspectY) { + [view->impl->window setContentAspectRatio:sizePoints(view, + view->minAspectX, + view->minAspectY)]; + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus puglSetTransientFor(PuglView* view, PuglNativeView parent) { - view->transientParent = parent; + view->transientParent = parent; - if (view->impl->window) { - NSWindow* parentWindow = [(NSView*)parent window]; - if (parentWindow) { - [parentWindow addChildWindow:view->impl->window - ordered:NSWindowAbove]; - return PUGL_SUCCESS; - } - } + if (view->impl->window) { + NSWindow* parentWindow = [(NSView*)parent window]; + if (parentWindow) { + [parentWindow addChildWindow:view->impl->window ordered:NSWindowAbove]; + return PUGL_SUCCESS; + } + } - return PUGL_FAILURE; + return PUGL_FAILURE; } const void* @@ -1370,57 +1383,57 @@ puglGetClipboard(PuglView* const view, const char** const type, size_t* const len) { - NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; + NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; - if ([[pasteboard types] containsObject:NSStringPboardType]) { - const NSString* str = [pasteboard stringForType:NSStringPboardType]; - const char* utf8 = [str UTF8String]; + if ([[pasteboard types] containsObject:NSStringPboardType]) { + const NSString* str = [pasteboard stringForType:NSStringPboardType]; + const char* utf8 = [str UTF8String]; - puglSetBlob(&view->clipboard, utf8, strlen(utf8) + 1); - } + puglSetBlob(&view->clipboard, utf8, strlen(utf8) + 1); + } - return puglGetInternalClipboard(view, type, len); + return puglGetInternalClipboard(view, type, len); } static NSCursor* puglGetNsCursor(const PuglCursor cursor) { - switch (cursor) { - case PUGL_CURSOR_ARROW: - return [NSCursor arrowCursor]; - case PUGL_CURSOR_CARET: - return [NSCursor IBeamCursor]; - case PUGL_CURSOR_CROSSHAIR: - return [NSCursor crosshairCursor]; - case PUGL_CURSOR_HAND: - return [NSCursor pointingHandCursor]; - case PUGL_CURSOR_NO: - return [NSCursor operationNotAllowedCursor]; - case PUGL_CURSOR_LEFT_RIGHT: - return [NSCursor resizeLeftRightCursor]; - case PUGL_CURSOR_UP_DOWN: - return [NSCursor resizeUpDownCursor]; - } - - return NULL; + switch (cursor) { + case PUGL_CURSOR_ARROW: + return [NSCursor arrowCursor]; + case PUGL_CURSOR_CARET: + return [NSCursor IBeamCursor]; + case PUGL_CURSOR_CROSSHAIR: + return [NSCursor crosshairCursor]; + case PUGL_CURSOR_HAND: + return [NSCursor pointingHandCursor]; + case PUGL_CURSOR_NO: + return [NSCursor operationNotAllowedCursor]; + case PUGL_CURSOR_LEFT_RIGHT: + return [NSCursor resizeLeftRightCursor]; + case PUGL_CURSOR_UP_DOWN: + return [NSCursor resizeUpDownCursor]; + } + + return NULL; } PuglStatus puglSetCursor(PuglView* view, PuglCursor cursor) { - PuglInternals* const impl = view->impl; - NSCursor* const cur = puglGetNsCursor(cursor); - if (!cur) { - return PUGL_FAILURE; - } + PuglInternals* const impl = view->impl; + NSCursor* const cur = puglGetNsCursor(cursor); + if (!cur) { + return PUGL_FAILURE; + } - impl->cursor = cur; + impl->cursor = cur; - if (impl->mouseTracked) { - [cur set]; - } + if (impl->mouseTracked) { + [cur set]; + } - return PUGL_SUCCESS; + return PUGL_SUCCESS; } PuglStatus @@ -1429,24 +1442,23 @@ puglSetClipboard(PuglView* const view, const void* const data, const size_t len) { - NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; - const char* const str = (const char*)data; + NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; + const char* const str = (const char*)data; - PuglStatus st = puglSetInternalClipboard(view, type, data, len); - if (st) { - return st; - } + PuglStatus st = puglSetInternalClipboard(view, type, data, len); + if (st) { + return st; + } - NSString* nsString = [NSString stringWithUTF8String:str]; - if (nsString) { - [pasteboard - declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] - owner:nil]; + NSString* nsString = [NSString stringWithUTF8String:str]; + if (nsString) { + [pasteboard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] + owner:nil]; - [pasteboard setString:nsString forType:NSStringPboardType]; + [pasteboard setString:nsString forType:NSStringPboardType]; - return PUGL_SUCCESS; - } + return PUGL_SUCCESS; + } - return PUGL_UNKNOWN_ERROR; + return PUGL_UNKNOWN_ERROR; } |