From 514718e037ac9753abea9c389b2355e94859c8ac Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 30 Oct 2025 20:03:25 +0000 Subject: [PATCH] UIViewComponentPeer: Fix bug where onscreen keyboard would fail to follow view orientation The important part seems to be initialising the UIWindow directly with the UIWindowScene, instead of initialising it with a frame and then assigning a scene later on. --- .../native/juce_UIViewComponentPeer_ios.mm | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm b/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm index e6c7e201e0..ea33441e56 100644 --- a/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm +++ b/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm @@ -544,19 +544,62 @@ private: [controller setNeedsStatusBarAppearanceUpdate]; } - void windowSceneChanged() override + void updateSceneForWindow() { if (isSharedWindow) return; - if (@available (iOS 13, *)) + auto* newWindow = std::invoke ([&]() -> JuceUIWindow* { - window.windowScene = windowSceneTracker->getWindowScene(); + if (@available (iOS 13, *)) + { + if (auto* scene = windowSceneTracker->getWindowScene()) + return [[JuceUIWindow alloc] initWithWindowScene: scene]; + } + else if (window == nil) + { + auto r = convertToCGRect (component.getBounds()); + r.origin.y = [UIScreen mainScreen].bounds.size.height - (r.origin.y + r.size.height); + + return [[JuceUIWindow alloc] initWithFrame: r]; + } + + return nil; + }); + + if (newWindow == nil) + return; + + if (window != nil) + { + [(JuceUIWindow*) window setOwner: nullptr]; + + if (@available (iOS 13, *)) + window.windowScene = nil; + + [window release]; + window = nil; } + [newWindow setOwner: this]; + newWindow.rootViewController = controller; + newWindow.hidden = ! isShowing(); + newWindow.opaque = component.isOpaque(); + newWindow.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0]; + + if (component.isAlwaysOnTop()) + newWindow.windowLevel = UIWindowLevelAlert; + + window = newWindow; + updateScreenBounds(); } + void windowSceneChanged() override + { + updateSceneForWindow(); + } + //============================================================================== class AsyncRepaintMessage final : public CallbackMessage { @@ -1768,27 +1811,12 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, r = convertToCGRect (component.getBounds()); r.origin.y = [UIScreen mainScreen].bounds.size.height - (r.origin.y + r.size.height); - window = [[JuceUIWindow alloc] initWithFrame: r]; - - if (@available (iOS 13, *)) - { - window.windowScene = windowSceneTracker->getWindowScene(); - } - - [((JuceUIWindow*) window) setOwner: this]; - controller = [[JuceUIViewController alloc] init]; controller.view = view; - window.rootViewController = controller; - - window.hidden = true; - window.opaque = component.isOpaque(); - window.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0]; - - if (component.isAlwaysOnTop()) - window.windowLevel = UIWindowLevelAlert; view.frame = CGRectMake (0, 0, r.size.width, r.size.height); + + updateSceneForWindow(); } setTitle (component.getName()); @@ -1811,7 +1839,7 @@ UIViewComponentPeer::~UIViewComponentPeer() [view release]; [controller release]; - if (! isSharedWindow) + if (! isSharedWindow && window != nil) { [((JuceUIWindow*) window) setOwner: nil]; @@ -1825,7 +1853,7 @@ UIViewComponentPeer::~UIViewComponentPeer() //============================================================================== void UIViewComponentPeer::setVisible (bool shouldBeVisible) { - if (! isSharedWindow) + if (! isSharedWindow && window != nil) window.hidden = ! shouldBeVisible; view.hidden = ! shouldBeVisible; @@ -1854,7 +1882,9 @@ void UIViewComponentPeer::setBounds (const Rectangle& newBounds, const bool } else { - window.frame = convertToCGRect (newBounds); + if (window != nil) + window.frame = convertToCGRect (newBounds); + view.frame = CGRectMake (0, 0, (CGFloat) newBounds.getWidth(), (CGFloat) newBounds.getHeight()); handleMovedOrResized(); @@ -1894,7 +1924,8 @@ Point UIViewComponentPeer::globalToLocal (Point screenPosition) void UIViewComponentPeer::setAlpha (float newAlpha) { - [view.window setAlpha: (CGFloat) newAlpha]; + if (view.window != nil) + [view.window setAlpha: (CGFloat) newAlpha]; } void UIViewComponentPeer::setFullScreen (bool shouldBeFullScreen) @@ -1972,7 +2003,7 @@ bool UIViewComponentPeer::contains (Point localPos, bool trueIfInAChildWind bool UIViewComponentPeer::setAlwaysOnTop (bool alwaysOnTop) { - if (! isSharedWindow) + if (! isSharedWindow && window != nil) window.windowLevel = alwaysOnTop ? UIWindowLevelAlert : UIWindowLevelNormal; return true;