diff options
Diffstat (limited to 'src/mac.m')
-rw-r--r-- | src/mac.m | 316 |
1 files changed, 124 insertions, 192 deletions
@@ -7,9 +7,10 @@ #include "mac.h" #include "internal.h" +#include "macros.h" #include "platform.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> #import <Cocoa/Cocoa.h> @@ -121,7 +122,7 @@ viewScreen(const PuglView* view) } static NSRect -nsRectToPoints(PuglView* view, const NSRect rect) +nsRectToPoints(const PuglView* view, const NSRect rect) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -132,7 +133,7 @@ nsRectToPoints(PuglView* view, const NSRect rect) } static NSRect -nsRectFromPoints(PuglView* view, const NSRect rect) +nsRectFromPoints(const PuglView* view, const NSRect rect) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -143,21 +144,15 @@ nsRectFromPoints(PuglView* view, const NSRect rect) } static NSPoint -nsPointFromPoints(PuglView* view, const NSPoint point) +nsPointFromPoints(const PuglView* view, const NSPoint point) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor); } -static NSRect -rectToNsRect(const PuglRect rect) -{ - return NSMakeRect(rect.x, rect.y, rect.width, rect.height); -} - static NSSize -sizePoints(PuglView* view, const double width, const double height) +sizePoints(PuglView* view, const PuglSpan width, const PuglSpan height) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -199,7 +194,7 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) const PuglConfigureEvent ev = { PUGL_CONFIGURE, - 0, + 0U, (PuglCoord)framePx.origin.x, (PuglCoord)framePx.origin.y, (PuglSpan)framePx.size.width, @@ -249,7 +244,7 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) const PuglConfigureEvent ev = { PUGL_CONFIGURE, - 0, + 0U, (PuglCoord)contentPx.origin.x, (PuglCoord)(screenHeight - contentPx.origin.y - contentPx.size.height), (PuglSpan)contentPx.size.width, @@ -331,7 +326,7 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) const PuglExposeEvent ev = { PUGL_EXPOSE, - 0, + 0U, (PuglCoord)(rect.origin.x * scaleFactor), (PuglCoord)viewY, (PuglSpan)(rect.size.width * scaleFactor), @@ -345,9 +340,9 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) - (NSSize)intrinsicContentSize { - const PuglViewSize defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE]; + const PuglArea defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE]; - return puglIsValidSize(defaultSize) + return puglIsValidArea(defaultSize) ? sizePoints(puglview, defaultSize.width, defaultSize.height) : NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); } @@ -463,7 +458,7 @@ keySymToSpecial(const NSEvent* const ev) return PUGL_KEY_PAD_9; } - return (PuglKey)0; + return PUGL_KEY_NONE; } - (void)updateTrackingAreas @@ -496,7 +491,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglCrossingEvent ev = { type, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -537,7 +532,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglMotionEvent ev = { PUGL_MOTION, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -572,7 +567,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglButtonEvent ev = { PUGL_BUTTON_PRESS, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -593,7 +588,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglButtonEvent ev = { PUGL_BUTTON_RELEASE, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -635,9 +630,9 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) double dx = -[event scrollingDeltaX]; double dy = [event scrollingDeltaY]; - if (![event hasPreciseScrollingDeltas]) { - dx *= 10.0; - dy *= 10.0; + if ([event hasPreciseScrollingDeltas]) { + dx /= 20.0; + dy /= 20.0; } const PuglScrollDirection dir = @@ -652,7 +647,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const PuglScrollEvent ev = { PUGL_SCROLL, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -684,7 +679,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const PuglKeyEvent ev = { PUGL_KEY_PRESS, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -715,7 +710,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const PuglKeyEvent ev = { PUGL_KEY_RELEASE, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -827,7 +822,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) PuglTextEvent ev = { PUGL_TEXT, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -856,7 +851,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) - (void)flagsChanged:(NSEvent*)event { const uint32_t mods = getModifiers(event); - PuglKey special = (PuglKey)0; + PuglKey special = PUGL_KEY_NONE; const uint16_t keyCode = [event keyCode]; if (flagDiffers(mods, puglview->impl->mods, PUGL_MOD_SHIFT)) { @@ -877,7 +872,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) const bool release = [event type] == NSEventTypeKeyUp; const PuglKeyEvent ev = {release ? PUGL_KEY_RELEASE : PUGL_KEY_PRESS, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -919,7 +914,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) - (void)timerTick:(NSTimer*)userTimer { const NSNumber* userInfo = userTimer.userInfo; - const PuglTimerEvent ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue}; + const PuglTimerEvent ev = {PUGL_TIMER, 0U, userInfo.unsignedLongValue}; PuglEvent timerEvent; timerEvent.timer = ev; @@ -984,7 +979,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) { (void)notification; - PuglEvent ev = {{PUGL_FOCUS_IN, 0}}; + PuglEvent ev = {{PUGL_FOCUS_IN, 0U}}; ev.focus.mode = PUGL_CROSSING_NORMAL; puglDispatchEvent(window->puglview, &ev); } @@ -993,7 +988,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) { (void)notification; - PuglEvent ev = {{PUGL_FOCUS_OUT, 0}}; + PuglEvent ev = {{PUGL_FOCUS_OUT, 0U}}; ev.focus.mode = PUGL_CROSSING_NORMAL; puglDispatchEvent(window->puglview, &ev); } @@ -1117,12 +1112,13 @@ updateSizeHint(PuglView* const view, const PuglSizeHint hint) { const PuglSpan width = view->sizeHints[hint].width; const PuglSpan height = view->sizeHints[hint].height; - if (!puglIsValidSize(view->sizeHints[hint])) { + if (!puglIsValidArea(view->sizeHints[hint])) { return PUGL_FAILURE; } switch (hint) { case PUGL_DEFAULT_SIZE: + case PUGL_CURRENT_SIZE: break; case PUGL_MIN_SIZE: @@ -1153,30 +1149,9 @@ updateSizeHints(PuglView* const view) } } -static PuglRect -getInitialFrame(PuglView* const view) +PuglPoint +puglGetAncestorCenter(const PuglView* const view) { - if (view->lastConfigure.type == PUGL_CONFIGURE) { - // Use the last configured frame - const PuglRect frame = {view->lastConfigure.x, - view->lastConfigure.y, - view->lastConfigure.width, - view->lastConfigure.height}; - return frame; - } - - const int x = view->defaultX; - const int y = view->defaultY; - if (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) { - // Use the default position set with puglSetPosition while unrealized - const PuglRect frame = {(PuglCoord)x, - (PuglCoord)y, - view->sizeHints[PUGL_DEFAULT_SIZE].width, - view->sizeHints[PUGL_DEFAULT_SIZE].height}; - return frame; - } - - // Get a bounding rect from the transient parent or the screen const NSScreen* const screen = viewScreen(view); const NSRect boundsPt = rectFromScreen(screen, @@ -1184,17 +1159,11 @@ getInitialFrame(PuglView* const view) ? [[(const NSView*)view->transientParent window] frame] : [screen frame]); - // Center the frame around the center of the bounding rectangle - const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; - const NSRect boundsPx = nsRectFromPoints(view, boundsPt); - const double centerX = boundsPx.origin.x + boundsPx.size.width / 2; - const double centerY = boundsPx.origin.y + boundsPx.size.height / 2; - - const PuglRect frame = {(PuglCoord)(centerX - (defaultSize.width / 2U)), - (PuglCoord)(centerY - (defaultSize.height / 2U)), - view->sizeHints[PUGL_DEFAULT_SIZE].width, - view->sizeHints[PUGL_DEFAULT_SIZE].height}; - return frame; + const NSRect boundsPx = nsRectFromPoints(view, boundsPt); + const PuglPoint center = { + (PuglCoord)(boundsPx.origin.x + (boundsPx.size.width / 2.0)), + (PuglCoord)(boundsPx.origin.y + (boundsPx.size.height / 2.0))}; + return center; } PuglStatus @@ -1242,11 +1211,12 @@ puglRealize(PuglView* view) CVDisplayLinkRelease(link); } - // Get the initial frame to use from the defaults or last configuration - const PuglRect initialFrame = getInitialFrame(view); + // Get the initial size and position from the defaults or last configuration + const PuglArea size = puglGetInitialSize(view); + const PuglPoint pos = puglGetInitialPosition(view, size); // Convert frame to points - const NSRect framePx = rectToNsRect(initialFrame); + const NSRect framePx = NSMakeRect(pos.x, pos.y, size.width, size.height); const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor, framePx.origin.y / scaleFactor, framePx.size.width / scaleFactor, @@ -1272,7 +1242,7 @@ puglRealize(PuglView* view) NSLayoutRelationGreaterThanOrEqual, view->sizeHints[PUGL_MIN_SIZE].height)]; - if (puglIsValidSize(view->sizeHints[PUGL_MAX_SIZE])) { + if (puglIsValidArea(view->sizeHints[PUGL_MAX_SIZE])) { [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView, NSLayoutAttributeWidth, @@ -1332,8 +1302,17 @@ puglRealize(PuglView* view) ((NSWindow*)window).delegate = [[PuglWindowDelegate alloc] initWithPuglWindow:window]; - // Set basic window hints and attributes - puglSetFrame(view, initialFrame); + // Set window frame + const NSRect screenPt = rectToScreen(screen, framePt); + const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; + [impl->window setFrame:winFrame display:NO]; + + // Resize views and move them to (0, 0) + const NSRect sizePx = {{0, 0}, {framePx.size.width, framePx.size.height}}; + const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; + [impl->wrapperView setFrame:sizePt]; + [impl->drawView setFrame:sizePt]; + puglSetTransientParent(view, view->transientParent); updateSizeHints(view); @@ -1605,14 +1584,6 @@ puglSendEvent(PuglView* view, const PuglEvent* event) return PUGL_UNSUPPORTED; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglWaitForEvent(PuglView* view) -{ - return puglPollEvents(view->world, -1.0); -} -#endif - PuglStatus puglUpdate(PuglWorld* world, const double timeout) { @@ -1650,14 +1621,6 @@ puglUpdate(PuglWorld* world, const double timeout) return PUGL_SUCCESS; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglProcessEvents(PuglView* view) -{ - return puglDispatchEvents(view->world); -} -#endif - double puglGetTime(const PuglWorld* world) { @@ -1669,22 +1632,37 @@ puglGetTime(const PuglWorld* world) } PuglStatus -puglPostRedisplay(PuglView* view) +puglObscureView(PuglView* view) { [view->impl->drawView setNeedsDisplay:YES]; return PUGL_SUCCESS; } PuglStatus -puglPostRedisplayRect(PuglView* view, const PuglRect rect) +puglObscureRegion(PuglView* view, + const int x, + const int y, + const unsigned width, + const unsigned height) { - const NSRect rectPx = { - {(double)rect.x, - (double)view->lastConfigure.height - (rect.y + rect.height)}, - {(double)rect.width, (double)rect.height}, - }; + if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) { + return PUGL_BAD_PARAMETER; + } + + const PuglSpan viewHeight = view->lastConfigure.height; - [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; + const int cx = MAX(0, x); + const int cy = MAX(0, viewHeight - y - (int)height); + const unsigned cw = MIN(view->lastConfigure.width, width); + const unsigned ch = MIN(view->lastConfigure.height, height); + + if (cw == view->lastConfigure.width && ch == view->lastConfigure.height) { + [view->impl->drawView setNeedsDisplay:YES]; + } else { + const NSRect rectPx = NSMakeRect(cx, cy, cw, ch); + + [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; + } return PUGL_SUCCESS; } @@ -1729,108 +1707,36 @@ puglGetScaleFactor(const PuglView* const view) return [viewScreen(view) backingScaleFactor]; } -PuglStatus -puglSetFrame(PuglView* view, const PuglRect frame) -{ - PuglInternals* const impl = view->impl; - const NSRect framePx = rectToNsRect(frame); - const NSRect framePt = nsRectToPoints(view, framePx); - - if (!impl->wrapperView) { - // Set defaults to be used when realized - view->defaultX = frame.x; - view->defaultY = frame.y; - view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)frame.width; - view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)frame.height; - return PUGL_SUCCESS; - } - - if (impl->window) { - const NSRect screenPt = rectToScreen(viewScreen(view), framePt); - - // Move and resize window to fit new content rect - const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; - [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]; - [impl->wrapperView setFrame:sizePt]; - [impl->drawView setFrame:sizePt]; - [impl->window dispatchCurrentConfiguration]; - return PUGL_SUCCESS; - } - - // Resize view - const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height); - const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; - - [impl->wrapperView setFrame:framePt]; - [impl->drawView setFrame:sizePt]; - return dispatchCurrentChildViewConfiguration(view); -} - -PuglStatus -puglSetPosition(PuglView* const view, const int x, const int y) +static PuglStatus +puglSetWindowPosition(PuglView* const view, const int x, const int y) { - if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) { - return PUGL_BAD_PARAMETER; - } - PuglInternals* const impl = view->impl; - if (!impl->wrapperView) { - // Set defaults to be used when realized - view->defaultX = x; - view->defaultY = y; - return PUGL_SUCCESS; - } - const PuglRect frame = {(PuglCoord)x, - (PuglCoord)y, - view->lastConfigure.width, - view->lastConfigure.height}; + const NSRect framePx = + NSMakeRect(x, y, view->lastConfigure.width, view->lastConfigure.height); + + const NSRect framePt = nsRectToPoints(view, framePx); if (impl->window) { // Adjust top-level window frame - return puglSetFrame(view, frame); + const NSRect screenPt = rectToScreen(viewScreen(view), framePt); + [impl->window setFrameOrigin:screenPt.origin]; + return PUGL_SUCCESS; } // Set wrapper view origin - const NSRect framePx = rectToNsRect(frame); - const NSRect framePt = nsRectToPoints(view, framePx); [impl->wrapperView setFrameOrigin:framePt.origin]; - // Set draw view origin - const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height); - const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx]; - [impl->drawView setFrameOrigin:drawPt.origin]; - // Dispatch new configuration return dispatchCurrentChildViewConfiguration(view); } -PuglStatus -puglSetSize(PuglView* const view, const unsigned width, const unsigned height) +static PuglStatus +puglSetWindowSize(PuglView* const view, + const unsigned width, + const unsigned height) { - if (width > INT16_MAX || height > INT16_MAX) { - return PUGL_BAD_PARAMETER; - } - PuglInternals* const impl = view->impl; - if (!impl->wrapperView) { - // Set defaults to be used when realized - view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width; - view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height; - return PUGL_SUCCESS; - } - - if (impl->window) { - // Adjust top-level window frame - PuglRect frame = puglGetFrame(view); - frame.width = (PuglSpan)width; - frame.height = (PuglSpan)height; - return puglSetFrame(view, frame); - } // Set wrapper view size const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -1842,24 +1748,50 @@ puglSetSize(PuglView* const view, const unsigned width, const unsigned height) const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx]; [impl->drawView setFrameSize:drawPt.size]; + if (impl->window) { + const NSRect framePx = + NSMakeRect(view->lastConfigure.x, view->lastConfigure.y, width, height); + const NSRect framePt = nsRectToPoints(view, framePx); + const NSRect screenPt = rectToScreen(viewScreen(view), framePt); + + // Resize window to fit new content rect + const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; + [impl->window setFrame:winFrame display:NO]; + [impl->window dispatchCurrentConfiguration]; + } + // Dispatch new configuration return dispatchCurrentChildViewConfiguration(view); } PuglStatus -puglSetSizeHint(PuglView* const view, - const PuglSizeHint hint, - const PuglSpan width, - const PuglSpan height) +puglSetPositionHint(PuglView* const view, + const PuglPositionHint hint, + const int x, + const int y) { - if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) { + if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) { return PUGL_BAD_PARAMETER; } - view->sizeHints[hint].width = width; - view->sizeHints[hint].height = height; + view->positionHints[hint].x = (PuglCoord)x; + view->positionHints[hint].y = (PuglCoord)y; + + return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y) + : PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const unsigned width, + const unsigned height) +{ + const PuglStatus st = puglStoreSizeHint(view, hint, width, height); - return view->impl->window ? updateSizeHint(view, hint) : PUGL_SUCCESS; + return st ? st + : (hint == PUGL_CURRENT_SIZE) ? puglSetWindowSize(view, width, height) + : updateSizeHint(view, hint); } PuglStatus @@ -1887,7 +1819,7 @@ puglPaste(PuglView* const view) { const PuglDataOfferEvent offer = { PUGL_DATA_OFFER, - 0, + 0U, puglGetTime(view->world), }; |