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 0eaecb5af3352..58abf2cc87bd4 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 233b245c1bcaa..4fffceb7acb72 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 a5cc25ec2e131..04974aeaf0b23 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 2f12f8cd0b101..f399f4ebb83c9 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 a9c0a49d1707a..01450311687ee 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 @@ - (void)updateDrawableSize 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 20375d0f8e2db..6169ccfa022b4 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 b01714535f329..7fec719b35037 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -148,6 +148,11 @@ - (void)setSDLWindow:(SDL_Window *)window 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)) {