From c717a20ec87a17ef79b00519e187d6985040a1ea Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 17 Mar 2026 12:25:13 -0700 Subject: [PATCH] Fixed initial window size and placement on visionOS --- src/video/uikit/SDL_uikitmetalview.m | 5 +++++ src/video/uikit/SDL_uikitvideo.m | 4 +++- src/video/uikit/SDL_uikitwindow.m | 21 +++++++++++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m index da0a8edd4f..596b311165 100644 --- a/src/video/uikit/SDL_uikitmetalview.m +++ b/src/video/uikit/SDL_uikitmetalview.m @@ -69,6 +69,11 @@ size.width *= self.layer.contentsScale; size.height *= self.layer.contentsScale; + // Skip invalid sizes (can happen on visionOS before scene geometry is applied) + if (size.width <= 0 || size.height <= 0) { + return; + } + CAMetalLayer *metallayer = ((CAMetalLayer *)self.layer); if (metallayer.drawableSize.width != size.width || metallayer.drawableSize.height != size.height) { diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 43fab3afcd..d31f70a13d 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -213,7 +213,9 @@ SDL_SystemTheme UIKit_GetSystemTheme(void) #ifdef SDL_PLATFORM_VISIONOS CGRect UIKit_ComputeViewFrame(SDL_Window *window) { - return CGRectMake(window->x, window->y, window->w, window->h); + // View origin is always (0,0) relative to the UIWindow. + // window->x/y are screen-level positions (often SDL_WINDOWPOS_UNDEFINED). + return CGRectMake(0, 0, window->w, window->h); } #else CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen) diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index dd6dc27bd7..3f1f1b464d 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -186,6 +186,23 @@ bool UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti } if (scene) { uiwindow = [[UIWindow alloc] initWithWindowScene:scene]; + +#ifdef SDL_PLATFORM_VISIONOS + /* On visionOS, the window scene may not have its final geometry yet + * when the UIWindow is first created. Request the desired size now + * and set the UIWindow frame to match so views have valid initial + * dimensions before the async geometry update completes. */ + CGSize desiredSize = CGSizeMake(window->w, window->h); + uiwindow.frame = CGRectMake(0, 0, desiredSize.width, desiredSize.height); + + UIWindowSceneGeometryPreferences *preferences = + [[UIWindowSceneGeometryPreferencesVision alloc] initWithSize:desiredSize]; + [scene requestGeometryUpdateWithPreferences:preferences errorHandler:^(NSError * _Nonnull error) { + SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, + "Initial geometry request failed: %s", + [[error localizedDescription] UTF8String]); + }]; +#endif } } if (!uiwindow) { @@ -214,10 +231,6 @@ bool UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti if (!SetupWindowData(_this, window, uiwindow, true)) { return false; } - -#ifdef SDL_PLATFORM_VISIONOS - SDL_SetWindowSize(window, window->w, window->h); -#endif } return true;