From b98e1e9ef05608b627665077b9b4c07d8b3a18eb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 24 Jul 2024 15:10:15 -0700 Subject: [PATCH] Fixed the render viewport not updating when the metal view resizes When the phone is in portrait mode and the window is in landscape mode, the view changes orientation after layoutSubviews runs. In this case we need some way of notifying the application that the Metal view has changed. --- include/SDL3/SDL_events.h | 1 + src/events/SDL_events.c | 1 + src/render/SDL_render.c | 3 ++- src/test/SDL_test_common.c | 4 ++++ src/video/uikit/SDL_uikitmetalview.m | 9 ++++++++- src/video/uikit/SDL_uikitview.h | 1 + src/video/uikit/SDL_uikitview.m | 5 +++++ 7 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 0eaecb5af3..58abf2cc87 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -130,6 +130,7 @@ typedef enum SDL_EventType SDL_EVENT_WINDOW_MOVED, /**< Window has been moved to data1, data2 */ SDL_EVENT_WINDOW_RESIZED, /**< Window has been resized to data1xdata2 */ SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED,/**< The pixel size of the window has changed to data1xdata2 */ + SDL_EVENT_WINDOW_METAL_VIEW_RESIZED,/**< The pixel size of a Metal view associated with the window has changed */ SDL_EVENT_WINDOW_MINIMIZED, /**< Window has been minimized */ SDL_EVENT_WINDOW_MAXIMIZED, /**< Window has been maximized */ SDL_EVENT_WINDOW_RESTORED, /**< Window has been restored to normal size and position */ diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 233b245c1b..4fffceb7ac 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -502,6 +502,7 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOVED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESIZED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_METAL_VIEW_RESIZED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MINIMIZED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MAXIMIZED); diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index a5cc25ec2e..04974aeaf0 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -830,7 +830,8 @@ static int SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event) } if (event->type == SDL_EVENT_WINDOW_RESIZED || - event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) { + event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED || + event->type == SDL_EVENT_WINDOW_METAL_VIEW_RESIZED) { UpdateMainViewDimensions(renderer); UpdateLogicalPresentation(renderer); } else if (event->type == SDL_EVENT_WINDOW_HIDDEN) { diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 2f12f8cd0b..f399f4ebb8 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1614,6 +1614,10 @@ static void SDLTest_PrintEvent(const SDL_Event *event) SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed pixel size to %" SDL_PRIs32 "x%" SDL_PRIs32, event->window.windowID, event->window.data1, event->window.data2); break; + case SDL_EVENT_WINDOW_METAL_VIEW_RESIZED: + SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed metal view size", + event->window.windowID); + break; case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED: { SDL_Rect rect; diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m index a9c0a49d17..0145031168 100644 --- a/src/video/uikit/SDL_uikitmetalview.m +++ b/src/video/uikit/SDL_uikitmetalview.m @@ -31,6 +31,7 @@ #if defined(SDL_VIDEO_DRIVER_UIKIT) && (defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL)) #include "../SDL_sysvideo.h" +#include "../../events/SDL_windowevents_c.h" #import "SDL_uikitwindow.h" #import "SDL_uikitmetalview.h" @@ -67,7 +68,13 @@ CGSize size = self.bounds.size; size.width *= self.layer.contentsScale; size.height *= self.layer.contentsScale; - ((CAMetalLayer *)self.layer).drawableSize = size; + + CAMetalLayer *metallayer = ((CAMetalLayer *)self.layer); + if (metallayer.drawableSize.width != size.width || + metallayer.drawableSize.height != size.height) { + metallayer.drawableSize = size; + SDL_SendWindowEvent([self getSDLWindow], SDL_EVENT_WINDOW_METAL_VIEW_RESIZED, 0, 0); + } } @end diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 20375d0f8e..6169ccfa02 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -32,6 +32,7 @@ - (instancetype)initWithFrame:(CGRect)frame; - (void)setSDLWindow:(SDL_Window *)window; +- (SDL_Window *)getSDLWindow; #if !defined(SDL_PLATFORM_TVOS) && defined(__IPHONE_13_4) - (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)); diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index b01714535f..7fec719b35 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -148,6 +148,11 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; sdlwindow = window; } +- (SDL_Window *)getSDLWindow +{ + return sdlwindow; +} + #if !defined(SDL_PLATFORM_TVOS) && defined(__IPHONE_13_4) - (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)) {