aboutsummaryrefslogtreecommitdiffstats
path: root/src/mac.m
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-01-07 19:27:14 -0500
committerDavid Robillard <d@drobilla.net>2023-01-07 20:27:35 -0500
commit4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b (patch)
tree63307cb14d43c7391b34f94ca0e532d8e9e01a09 /src/mac.m
parent677e13dcbb5b64ce85093b9ea5c14025964e35b9 (diff)
downloadpugl-4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b.tar.gz
pugl-4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b.tar.bz2
pugl-4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b.zip
Add support for special view types and styles
Diffstat (limited to 'src/mac.m')
-rw-r--r--src/mac.m207
1 files changed, 187 insertions, 20 deletions
diff --git a/src/mac.m b/src/mac.m
index 00b886c..72f5f9c 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -173,6 +173,27 @@ updateViewRect(PuglView* view)
}
}
+static PuglViewStyleFlags
+getCurrentViewStyleFlags(PuglView* const view)
+{
+ const bool isResizing = view->resizing;
+
+ if (!view->impl->window) {
+ return (isResizing ? PUGL_VIEW_STYLE_RESIZING : 0U);
+ }
+
+ const NSWindowStyleMask styleMask = [view->impl->window styleMask];
+
+ const bool isFullScreen = styleMask & NSWindowStyleMaskFullScreen;
+ const bool isMiniaturized = [view->impl->window isMiniaturized];
+ const bool isZoomed = [view->impl->window isZoomed];
+
+ return (isFullScreen ? PUGL_VIEW_STYLE_FULLSCREEN : 0U) |
+ (isMiniaturized ? PUGL_VIEW_STYLE_HIDDEN : 0U) |
+ (isZoomed ? (PUGL_VIEW_STYLE_TALL | PUGL_VIEW_STYLE_WIDE) : 0U) |
+ (isResizing ? PUGL_VIEW_STYLE_RESIZING : 0U);
+}
+
@implementation PuglWindow {
@public
PuglView* puglview;
@@ -201,6 +222,24 @@ updateViewRect(PuglView* view)
[self setContentSize:sizePoints(view, view->frame.width, view->frame.height)];
}
+- (PuglStatus)dispatchCurrentConfiguration
+{
+ const PuglConfigureEvent ev = {
+ PUGL_CONFIGURE,
+ 0,
+ puglview->frame.x,
+ puglview->frame.y,
+ puglview->frame.width,
+ puglview->frame.height,
+ getCurrentViewStyleFlags(puglview),
+ };
+
+ PuglEvent configureEvent;
+ configureEvent.configure = ev;
+
+ return puglDispatchEvent(puglview, &configureEvent);
+}
+
- (BOOL)canBecomeKeyWindow
{
return YES;
@@ -216,24 +255,25 @@ updateViewRect(PuglView* view)
[super setIsVisible:flag];
if (flag && puglview->stage < PUGL_VIEW_STAGE_MAPPED) {
- const PuglConfigureEvent ev = {
- PUGL_CONFIGURE,
- 0,
- puglview->frame.x,
- puglview->frame.y,
- puglview->frame.width,
- puglview->frame.height,
- };
-
- PuglEvent configureEvent;
- configureEvent.configure = ev;
- puglDispatchEvent(puglview, &configureEvent);
+ [self dispatchCurrentConfiguration];
puglDispatchSimpleEvent(puglview, PUGL_MAP);
} else if (!flag && puglview->stage == PUGL_VIEW_STAGE_MAPPED) {
puglDispatchSimpleEvent(puglview, PUGL_UNMAP);
}
}
+- (void)setIsZoomed:(BOOL)flag
+{
+ [super setIsZoomed:flag];
+
+ const bool wasZoomed = (puglview->lastConfigure.style &
+ (PUGL_VIEW_STYLE_TALL | PUGL_VIEW_STYLE_WIDE));
+
+ if (flag != wasZoomed) {
+ [self dispatchCurrentConfiguration];
+ }
+}
+
@end
@implementation PuglWrapperView {
@@ -263,6 +303,7 @@ updateViewRect(PuglView* view)
puglview->frame.y,
puglview->frame.width,
puglview->frame.height,
+ getCurrentViewStyleFlags(puglview),
};
PuglEvent configureEvent;
@@ -821,6 +862,11 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
puglDispatchSimpleEvent(puglview, PUGL_LOOP_ENTER);
}
+- (void)viewDidEndLiveResize
+{
+ puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE);
+}
+
- (void)viewWillDraw
{
puglDispatchSimpleEvent(puglview, PUGL_UPDATE);
@@ -837,16 +883,13 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
puglDispatchEvent(puglview, &timerEvent);
}
-- (void)viewDidEndLiveResize
-{
- puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE);
-}
-
@end
@interface PuglWindowDelegate : NSObject<NSWindowDelegate>
- (instancetype)initWithPuglWindow:(PuglWindow*)window;
+- (void)beginLiveResize:(NSNotification*)notification;
+- (void)endLiveResize:(NSNotification*)notification;
@end
@@ -863,6 +906,22 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
return self;
}
+- (void)beginLiveResize:(NSNotification*)notification
+{
+ (void)notification;
+
+ window->puglview->resizing = true;
+ [window dispatchCurrentConfiguration];
+}
+
+- (void)endLiveResize:(NSNotification*)notification
+{
+ (void)notification;
+
+ window->puglview->resizing = false;
+ [window dispatchCurrentConfiguration];
+}
+
- (BOOL)windowShouldClose:(id)sender
{
(void)sender;
@@ -896,6 +955,56 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
puglDispatchEvent(window->puglview, &ev);
}
+- (void)windowWillStartLiveResize:(NSNotification*)notification
+{
+ [self beginLiveResize:notification];
+}
+
+- (void)windowDidEndLiveResize:(NSNotification*)notification
+{
+ [self endLiveResize:notification];
+}
+
+- (void)windowWillMiniaturize:(NSNotification*)notification
+{
+ [self beginLiveResize:notification];
+}
+
+- (void)windowDidMiniaturize:(NSNotification*)notification
+{
+ [self endLiveResize:notification];
+}
+
+- (void)windowWillDeminiaturize:(NSNotification*)notification
+{
+ [self beginLiveResize:notification];
+}
+
+- (void)windowDidDeminiaturize:(NSNotification*)notification
+{
+ [self endLiveResize:notification];
+}
+
+- (void)windowWillEnterFullScreen:(NSNotification*)notification
+{
+ [self beginLiveResize:notification];
+}
+
+- (void)windowDidEnterFullScreen:(NSNotification*)notification
+{
+ [self endLiveResize:notification];
+}
+
+- (void)windowWillExitFullScreen:(NSNotification*)notification
+{
+ [self beginLiveResize:notification];
+}
+
+- (void)windowDidExitFullScreen:(NSNotification*)notification
+{
+ [self endLiveResize:notification];
+}
+
@end
PuglWorldInternals*
@@ -1278,11 +1387,69 @@ puglHasFocus(const PuglView* view)
[[impl->wrapperView window] firstResponder] == impl->wrapperView);
}
+static bool
+styleIsMaximized(const PuglViewStyleFlags flags)
+{
+ return (flags & PUGL_VIEW_STYLE_TALL) && (flags & PUGL_VIEW_STYLE_WIDE);
+}
+
PuglStatus
-puglRequestAttention(PuglView* view)
+puglSetViewStyle(PuglView* const view, const PuglViewStyleFlags flags)
{
- if (![view->impl->window isKeyWindow]) {
- [view->world->impl->app requestUserAttention:NSInformationalRequest];
+ NSWindow* const window = view->impl->window;
+ const PuglViewStyleFlags oldFlags = puglGetViewStyle(view);
+ if (!window) {
+ return PUGL_FAILURE;
+ }
+
+ for (uint32_t mask = 1U; mask <= PUGL_MAX_VIEW_STYLE_FLAG; mask <<= 1U) {
+ const bool oldValue = oldFlags & mask;
+ const bool newValue = flags & mask;
+ if (oldValue == newValue) {
+ continue;
+ }
+
+ switch (mask) {
+ case PUGL_VIEW_STYLE_MODAL:
+ case PUGL_VIEW_STYLE_TALL:
+ case PUGL_VIEW_STYLE_WIDE:
+ break;
+
+ case PUGL_VIEW_STYLE_HIDDEN:
+ if (newValue) {
+ [window miniaturize:window];
+ } else {
+ [window deminiaturize:window];
+ }
+ break;
+
+ case PUGL_VIEW_STYLE_FULLSCREEN:
+ if (newValue != ([window styleMask] & NSFullScreenWindowMask)) {
+ [window toggleFullScreen:nil];
+ }
+ break;
+
+ case PUGL_VIEW_STYLE_ABOVE:
+ case PUGL_VIEW_STYLE_BELOW:
+ break;
+
+ case PUGL_VIEW_STYLE_DEMANDING:
+ if (![window isKeyWindow]) {
+ [view->world->impl->app requestUserAttention:NSInformationalRequest];
+ }
+ break;
+
+ case PUGL_VIEW_STYLE_RESIZING:
+ case PUGL_VIEW_STYLE_MAPPED:
+ break;
+ }
+ }
+
+ // Handle maximization (MacOS doesn't have tall/wide styles)
+ const bool oldMaximized = styleIsMaximized(oldFlags);
+ const bool newMaximized = styleIsMaximized(flags);
+ if (oldMaximized != newMaximized) {
+ [window zoom:window];
}
return PUGL_SUCCESS;