diff --git a/src/platform/platform_macos.mm b/src/platform/platform_macos.mm index 3c874be..312360f 100644 --- a/src/platform/platform_macos.mm +++ b/src/platform/platform_macos.mm @@ -52,6 +52,14 @@ static PlatformWindow *g_current_window = nullptr; //////////////////////////////// // Objective-C helper classes +@interface ASmplAppDelegate : NSObject +@end + +@implementation ASmplAppDelegate +- (void)applicationDidFinishLaunching:(NSNotification *)notification { (void)notification; } +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { (void)sender; return YES; } +@end + @interface ASmplWindowDelegate : NSObject @end @@ -255,10 +263,17 @@ static ASmplMenuTarget *g_menu_target = nil; // Public API PlatformWindow *platform_create_window(PlatformWindowDesc *desc) { - // Ensure NSApplication is initialized + // Ensure NSApplication is initialized and properly launched [NSApplication sharedApplication]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + static ASmplAppDelegate *app_delegate = nil; + if (!app_delegate) { + app_delegate = [[ASmplAppDelegate alloc] init]; + [NSApp setDelegate:app_delegate]; + [NSApp finishLaunching]; + } + NSRect content_rect = NSMakeRect(0, 0, desc->width, desc->height); NSWindow *ns_window = [[NSWindow alloc] @@ -310,12 +325,22 @@ void platform_destroy_window(PlatformWindow *window) { B32 platform_poll_events(PlatformWindow *window) { @autoreleasepool { + // When the app is not active (e.g. during Cmd+Tab away), block until + // an event arrives instead of spinning. This keeps CPU near zero while + // backgrounded and lets macOS handle the app-switch animation smoothly. + BOOL is_active = [NSApp isActive]; + NSDate *deadline = is_active ? nil : [NSDate distantFuture]; + NSEvent *event; while ((event = [NSApp nextEventMatchingMask:NSEventMaskAny - untilDate:nil + untilDate:deadline inMode:NSDefaultRunLoopMode dequeue:YES])) { [NSApp sendEvent:event]; + // After processing one event while backgrounded, switch to + // non-blocking drain so we handle any remaining queued events + // (including the activation event that will flip isActive). + deadline = nil; } } return !window->should_close; diff --git a/src/renderer/renderer_metal.mm b/src/renderer/renderer_metal.mm index 48afb30..c97c31c 100644 --- a/src/renderer/renderer_metal.mm +++ b/src/renderer/renderer_metal.mm @@ -539,7 +539,8 @@ Renderer *renderer_create(RendererDesc *desc) { layer.device = r->device; layer.pixelFormat = MTLPixelFormatBGRA8Unorm; layer.framebufferOnly = YES; - layer.maximumDrawableCount = NUM_BACK_BUFFERS; + layer.displaySyncEnabled = YES; + layer.maximumDrawableCount = 3; NSWindow *window = [view window]; r->backing_scale = (F32)[window backingScaleFactor];