mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AUv3: Fix an issue in detecting the available screen user area
On at least iOS 26 using a temporary window frame is unreliable. This change tries to use an existing window for any non-standalone app. It also updates the details on any changes, such as when the device orientation changes.
This commit is contained in:
parent
32b4423ca8
commit
88af872d4d
8 changed files with 81 additions and 37 deletions
|
|
@ -651,42 +651,78 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
|
|||
return Orientations::convertToJuce (orientation);
|
||||
}
|
||||
|
||||
// The most straightforward way of retrieving the screen area available to an iOS app
|
||||
// seems to be to create a new window (which will take up all available space) and to
|
||||
// query its frame.
|
||||
struct TemporaryWindow
|
||||
struct WindowInfo
|
||||
{
|
||||
UIWindow* window = std::invoke ([&]
|
||||
explicit WindowInfo (const UIWindow* window)
|
||||
: bounds (convertToRectInt (window.frame)),
|
||||
safeInsets (window.safeAreaInsets.top,
|
||||
window.safeAreaInsets.left,
|
||||
window.safeAreaInsets.bottom,
|
||||
window.safeAreaInsets.right)
|
||||
{}
|
||||
|
||||
Rectangle<int> bounds;
|
||||
BorderSize<double> safeInsets;
|
||||
};
|
||||
|
||||
static const UIWindow* findWindow (const UIView* view)
|
||||
{
|
||||
if (view == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if (view.window != nullptr)
|
||||
return view.window;
|
||||
|
||||
return findWindow (view.superview);
|
||||
}
|
||||
|
||||
static const UIWindow* findWindow (const Desktop& desktop)
|
||||
{
|
||||
if (auto* c = desktop.getComponent (0))
|
||||
if (auto* p = static_cast<UIViewComponentPeer*> (c->getPeer()))
|
||||
if (auto* w = findWindow (p->view))
|
||||
return w;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static WindowInfo getWindowInfo (const Desktop& desktop)
|
||||
{
|
||||
if (! JUCEApplication::isStandaloneApp())
|
||||
if (const auto* window = findWindow (desktop))
|
||||
return WindowInfo { window };
|
||||
|
||||
const auto createTemporaryWindow = []()
|
||||
{
|
||||
if (@available (iOS 13, *))
|
||||
{
|
||||
SharedResourcePointer<WindowSceneTracker> windowSceneTracker;
|
||||
|
||||
if (auto* scene = windowSceneTracker->getWindowScene())
|
||||
return [[UIWindow alloc] initWithWindowScene: scene];
|
||||
return NSUniquePtr<UIWindow> { [[UIWindow alloc] initWithWindowScene: scene] };
|
||||
}
|
||||
|
||||
return [[UIWindow alloc] init];
|
||||
});
|
||||
~TemporaryWindow() noexcept { [window release]; }
|
||||
};
|
||||
return NSUniquePtr<UIWindow> { [[UIWindow alloc] init] };
|
||||
};
|
||||
|
||||
static Rectangle<int> getRecommendedWindowBounds()
|
||||
{
|
||||
return convertToRectInt (TemporaryWindow().window.frame);
|
||||
auto window (createTemporaryWindow());
|
||||
return WindowInfo { window.get() };
|
||||
}
|
||||
|
||||
static BorderSize<int> getSafeAreaInsets (float masterScale)
|
||||
static Rectangle<int> getRecommendedWindowBounds (const Desktop& desktop)
|
||||
{
|
||||
UIEdgeInsets safeInsets = TemporaryWindow().window.safeAreaInsets;
|
||||
return detail::WindowingHelpers::roundToInt (BorderSize<double> { safeInsets.top,
|
||||
safeInsets.left,
|
||||
safeInsets.bottom,
|
||||
safeInsets.right }.multipliedBy (1.0 / (double) masterScale));
|
||||
return getWindowInfo (desktop).bounds;
|
||||
}
|
||||
|
||||
static BorderSize<int> getSafeAreaInsets (const Desktop& desktop)
|
||||
{
|
||||
const auto masterScale = (double) desktop.getGlobalScaleFactor();
|
||||
const auto safeInsets = getWindowInfo (desktop).safeInsets;
|
||||
return detail::WindowingHelpers::roundToInt (safeInsets.multipliedBy (1.0 / masterScale));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Displays::findDisplays (float masterScale)
|
||||
void Displays::findDisplays (const Desktop& desktop)
|
||||
{
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
|
||||
static const auto keyboardShownSelector = @selector (juceKeyboardShown:);
|
||||
|
|
@ -716,7 +752,7 @@ void Displays::findDisplays (float masterScale)
|
|||
|
||||
addMethod (keyboardShownSelector, [] (id self, SEL, NSNotification* notification)
|
||||
{
|
||||
setKeyboardScreenBounds (self, [&]() -> BorderSize<double>
|
||||
setKeyboardScreenBounds (self, std::invoke ([&]() -> BorderSize<double>
|
||||
{
|
||||
auto* info = [notification userInfo];
|
||||
|
||||
|
|
@ -744,7 +780,7 @@ void Displays::findDisplays (float masterScale)
|
|||
result.setBottom (rect.getHeight());
|
||||
|
||||
return result;
|
||||
}());
|
||||
}));
|
||||
});
|
||||
|
||||
addMethod (keyboardHiddenSelector, [] (id self, SEL, NSNotification*)
|
||||
|
|
@ -777,9 +813,10 @@ void Displays::findDisplays (float masterScale)
|
|||
UIScreen* s = [UIScreen mainScreen];
|
||||
|
||||
Display d;
|
||||
const auto masterScale = desktop.getGlobalScaleFactor();
|
||||
d.totalArea = convertToRectInt ([s bounds]) / masterScale;
|
||||
d.userArea = getRecommendedWindowBounds() / masterScale;
|
||||
d.safeAreaInsets = getSafeAreaInsets (masterScale);
|
||||
d.userArea = getRecommendedWindowBounds (desktop) / masterScale;
|
||||
d.safeAreaInsets = getSafeAreaInsets (desktop);
|
||||
const auto scaledInsets = keyboardChangeDetector.getInsets().multipliedBy (1.0 / (double) masterScale);
|
||||
d.keyboardInsets = detail::WindowingHelpers::roundToInt (scaledInsets);
|
||||
d.isMain = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue