Browse Source

Fixed initial window size and placement on visionOS

Sam Lantinga 1 day ago
parent
commit
c717a20ec8

+ 5 - 0
src/video/uikit/SDL_uikitmetalview.m

@@ -69,6 +69,11 @@
     size.width *= self.layer.contentsScale;
     size.width *= self.layer.contentsScale;
     size.height *= 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);
     CAMetalLayer *metallayer = ((CAMetalLayer *)self.layer);
     if (metallayer.drawableSize.width != size.width ||
     if (metallayer.drawableSize.width != size.width ||
         metallayer.drawableSize.height != size.height) {
         metallayer.drawableSize.height != size.height) {

+ 3 - 1
src/video/uikit/SDL_uikitvideo.m

@@ -213,7 +213,9 @@ SDL_SystemTheme UIKit_GetSystemTheme(void)
 #ifdef SDL_PLATFORM_VISIONOS
 #ifdef SDL_PLATFORM_VISIONOS
 CGRect UIKit_ComputeViewFrame(SDL_Window *window)
 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
 #else
 CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)
 CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)

+ 17 - 4
src/video/uikit/SDL_uikitwindow.m

@@ -186,6 +186,23 @@ bool UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti
             }
             }
             if (scene) {
             if (scene) {
                 uiwindow = [[UIWindow alloc] initWithWindowScene: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) {
         if (!uiwindow) {
@@ -214,10 +231,6 @@ bool UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti
         if (!SetupWindowData(_this, window, uiwindow, true)) {
         if (!SetupWindowData(_this, window, uiwindow, true)) {
             return false;
             return false;
         }
         }
-
-#ifdef SDL_PLATFORM_VISIONOS
-        SDL_SetWindowSize(window, window->w, window->h);
-#endif
     }
     }
 
 
     return true;
     return true;