aboutsummaryrefslogtreecommitdiffstats
path: root/src/mac.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/mac.m')
-rw-r--r--src/mac.m331
1 files changed, 136 insertions, 195 deletions
diff --git a/src/mac.m b/src/mac.m
index cf7e8d2..41d358a 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -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,
@@ -326,11 +321,14 @@ dispatchCurrentChildViewConfiguration(PuglView* const view)
return;
}
+ const double viewY = (double)puglview->lastConfigure.height -
+ ((rect.origin.y + rect.size.height) * scaleFactor);
+
const PuglExposeEvent ev = {
PUGL_EXPOSE,
- 0,
+ 0U,
(PuglCoord)(rect.origin.x * scaleFactor),
- (PuglCoord)(rect.origin.y * scaleFactor),
+ (PuglCoord)viewY,
(PuglSpan)(rect.size.width * scaleFactor),
(PuglSpan)(rect.size.height * scaleFactor),
};
@@ -342,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);
}
@@ -460,7 +458,7 @@ keySymToSpecial(const NSEvent* const ev)
return PUGL_KEY_PAD_9;
}
- return (PuglKey)0;
+ return PUGL_KEY_NONE;
}
- (void)updateTrackingAreas
@@ -493,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,
@@ -534,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,
@@ -569,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,
@@ -590,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,
@@ -627,10 +625,16 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
- (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 NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+
+ double dx = -[event scrollingDeltaX];
+ double dy = [event scrollingDeltaY];
+ if ([event hasPreciseScrollingDeltas]) {
+ dx /= 20.0;
+ dy /= 20.0;
+ }
+
const PuglScrollDirection dir =
((dx == 0.0 && dy > 0.0)
? PUGL_SCROLL_UP
@@ -643,14 +647,14 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const PuglScrollEvent ev = {
PUGL_SCROLL,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
rloc.x,
[[NSScreen mainScreen] frame].size.height - rloc.y,
getModifiers(event),
- [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir,
+ dir,
dx,
dy,
};
@@ -675,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,
@@ -706,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,
@@ -818,7 +822,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
PuglTextEvent ev = {
PUGL_TEXT,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -847,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)) {
@@ -868,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,
@@ -910,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;
@@ -975,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);
}
@@ -984,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);
}
@@ -1108,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:
@@ -1144,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,
@@ -1175,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
@@ -1233,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,
@@ -1263,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,
@@ -1323,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);
@@ -1596,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)
{
@@ -1641,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)
{
@@ -1660,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;
+
+ 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)];
+ [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)];
+ }
return PUGL_SUCCESS;
}
@@ -1720,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];
@@ -1833,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
@@ -1878,7 +1819,7 @@ puglPaste(PuglView* const view)
{
const PuglDataOfferEvent offer = {
PUGL_DATA_OFFER,
- 0,
+ 0U,
puglGetTime(view->world),
};