Browse Source

Allow rendering during the modal resize loop on macOS

Fixes https://github.com/libsdl-org/SDL/issues/11508

(cherry picked from commit 9a43c08146a765fca166586e9739eb26c5309346)
Sam Lantinga 3 months ago
parent
commit
884c8b684a

+ 1 - 0
src/video/SDL_sysvideo.h

@@ -512,6 +512,7 @@ extern void SDL_OnWindowShown(SDL_Window *window);
 extern void SDL_OnWindowHidden(SDL_Window *window);
 extern void SDL_OnWindowMoved(SDL_Window *window);
 extern void SDL_OnWindowResized(SDL_Window *window);
+extern void SDL_OnWindowLiveResizeUpdate(SDL_Window *window);
 extern void SDL_OnWindowMinimized(SDL_Window *window);
 extern void SDL_OnWindowRestored(SDL_Window *window);
 extern void SDL_OnWindowEnter(SDL_Window *window);

+ 6 - 0
src/video/SDL_video.c

@@ -3179,6 +3179,12 @@ void SDL_OnWindowMoved(SDL_Window *window)
     }
 }
 
+void SDL_OnWindowLiveResizeUpdate(SDL_Window *window)
+{
+    /* Send an expose event so the application can redraw */
+    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
+}
+
 void SDL_OnWindowMinimized(SDL_Window *window)
 {
     if (!DisableUnsetFullscreenOnMinimize(_this)) {

+ 3 - 0
src/video/cocoa/SDL_cocoawindow.h

@@ -54,6 +54,7 @@ typedef enum
     NSInteger focusClickPending;
     int pendingWindowWarpX, pendingWindowWarpY;
     BOOL isDragAreaRunning;
+    NSTimer *liveResizeTimer;
 }
 
 -(BOOL) isTouchFromTrackpad:(NSEvent *)theEvent;
@@ -77,6 +78,8 @@ typedef enum
 /* Window delegate functionality */
 -(BOOL) windowShouldClose:(id) sender;
 -(void) windowDidExpose:(NSNotification *) aNotification;
+-(void) windowWillStartLiveResize:(NSNotification *)aNotification;
+-(void) windowDidEndLiveResize:(NSNotification *)aNotification;
 -(void) windowDidMove:(NSNotification *) aNotification;
 -(void) windowDidResize:(NSNotification *) aNotification;
 -(void) windowDidMiniaturize:(NSNotification *) aNotification;

+ 25 - 0
src/video/cocoa/SDL_cocoawindow.m

@@ -490,11 +490,14 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
     isMoving = NO;
     isDragAreaRunning = NO;
     pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
+    liveResizeTimer = nil;
 
     center = [NSNotificationCenter defaultCenter];
 
     if ([window delegate] != nil) {
         [center addObserver:self selector:@selector(windowDidExpose:) name:NSWindowDidExposeNotification object:window];
+        [center addObserver:self selector:@selector(windowWillStartLiveResize:) name:NSWindowWillStartLiveResizeNotification object:window];
+        [center addObserver:self selector:@selector(windowDidEndLiveResize:) name:NSWindowDidEndLiveResizeNotification object:window];
         [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window];
         [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window];
         [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:window];
@@ -628,6 +631,8 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
 
     if ([window delegate] != self) {
         [center removeObserver:self name:NSWindowDidExposeNotification object:window];
+        [center removeObserver:self name:NSWindowWillStartLiveResizeNotification object:window];
+        [center removeObserver:self name:NSWindowDidEndLiveResizeNotification object:window];
         [center removeObserver:self name:NSWindowDidMoveNotification object:window];
         [center removeObserver:self name:NSWindowDidResizeNotification object:window];
         [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:window];
@@ -738,6 +743,26 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
     SDL_SendWindowEvent(_data.window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
 }
 
+- (void)windowWillStartLiveResize:(NSNotification *)aNotification
+{
+    // We'll try to maintain 60 FPS during live resizing
+    const NSTimeInterval interval = 1.0 / 60.0;
+    liveResizeTimer = [NSTimer scheduledTimerWithTimeInterval:interval
+                                                      repeats:TRUE
+                                                        block:^(NSTimer *unusedTimer)
+    {
+        SDL_OnWindowLiveResizeUpdate(_data.window);
+    }];
+
+    [[NSRunLoop currentRunLoop] addTimer:liveResizeTimer forMode:NSRunLoopCommonModes];
+}
+
+- (void)windowDidEndLiveResize:(NSNotification *)aNotification
+{
+    [liveResizeTimer invalidate];
+    liveResizeTimer = nil;
+}
+
 - (void)windowWillMove:(NSNotification *)aNotification
 {
     if ([_data.nswindow isKindOfClass:[SDLWindow class]]) {

+ 1 - 2
src/video/windows/SDL_windowsevents.c

@@ -1335,8 +1335,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     case WM_TIMER:
     {
         if (wParam == (UINT_PTR)&s_ModalMoveResizeLoop) {
-            // Send an expose event so the application can redraw
-            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
+            SDL_OnWindowLiveResizeUpdate(data->window);
             return 0;
         }
     } break;