From 884c8b684abf280b5af825242b234e1c77470a54 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 23 Dec 2024 11:09:46 -0800
Subject: [PATCH] Allow rendering during the modal resize loop on macOS
Fixes https://github.com/libsdl-org/SDL/issues/11508
(cherry picked from commit 9a43c08146a765fca166586e9739eb26c5309346)
---
src/video/SDL_sysvideo.h | 1 +
src/video/SDL_video.c | 6 ++++++
src/video/cocoa/SDL_cocoawindow.h | 3 +++
src/video/cocoa/SDL_cocoawindow.m | 25 +++++++++++++++++++++++++
src/video/windows/SDL_windowsevents.c | 3 +--
5 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 3daff4cc5563d..0dc4364cd8bb9 100644
--- a/src/video/SDL_sysvideo.h
+++ b/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);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 91db5ebb78814..11a7dcf658eca 100644
--- a/src/video/SDL_video.c
+++ b/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)) {
diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h
index 0cf9e9a6ee737..ea1d5c1459c26 100644
--- a/src/video/cocoa/SDL_cocoawindow.h
+++ b/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;
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index 8e22a0c17c462..b9d4fe4f380f5 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -490,11 +490,14 @@ - (void)listen:(SDL_WindowData *)data
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 @@ - (void)close
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 @@ - (void)windowDidExpose:(NSNotification *)aNotification
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]]) {
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index bc636d4da978f..d7b8c3d7dc2b9 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/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;