diff --git a/modules/juce_core/native/juce_osx_ObjCHelpers.h b/modules/juce_core/native/juce_osx_ObjCHelpers.h index 62624f52cc0b..7a27f07cf655 100644 --- a/modules/juce_core/native/juce_osx_ObjCHelpers.h +++ b/modules/juce_core/native/juce_osx_ObjCHelpers.h @@ -193,6 +193,17 @@ NSRect makeNSRect (const RectangleType& r) noexcept } #endif +#if JUCE_IOS +template +CGRect makeCGRect (const RectangleType& r) noexcept +{ + return CGRectMake (static_cast (r.getX()), + static_cast (r.getY()), + static_cast (r.getWidth()), + static_cast (r.getHeight())); +} +#endif + #if JUCE_INTEL template struct NeedsStret { static constexpr auto value = sizeof (T) > 16; }; diff --git a/modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp index 602196d684d5..c6084d4bc7b5 100644 --- a/modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp +++ b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp @@ -150,8 +150,9 @@ JUCE_IMPLEMENT_SINGLETON (ContentSharer) ContentSharer::ContentSharer() {} ContentSharer::~ContentSharer() { clearSingletonInstance(); } -void ContentSharer::setParentComponent(Component* parentComponentToUse) { +void ContentSharer::setParentComponent(Component* parentComponentToUse, Component* sourceComponentToUse) { parentComponent = parentComponentToUse; + sourceComponent = sourceComponentToUse; } void ContentSharer::shareFiles (const Array& files, diff --git a/modules/juce_gui_basics/filebrowser/juce_ContentSharer.h b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.h index c061385327de..0c3a0e6becaa 100644 --- a/modules/juce_gui_basics/filebrowser/juce_ContentSharer.h +++ b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.h @@ -43,7 +43,7 @@ class JUCE_API ContentSharer : public DeletedAtShutdown * Sets the parent component to be used in subsequent calls to iOS native sharer. * Required to make ContentSharer work in AUv3 plugins. */ - void setParentComponent(Component* parentComponentToUse); + void setParentComponent(Component* parentComponent, Component* sourceComponent = nullptr); /** Shares the given files. Each URL should be either a full file path or it should point to a resource within the application bundle. For @@ -116,6 +116,7 @@ class JUCE_API ContentSharer : public DeletedAtShutdown std::function callback; Component* parentComponent = nullptr; + Component::SafePointer sourceComponent; #if JUCE_CONTENT_SHARING struct Pimpl diff --git a/modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp b/modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp index 43f43ccf528e..3c3a5274524d 100644 --- a/modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp +++ b/modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp @@ -34,7 +34,9 @@ class ContentSharer::ContentSharerNativeImpl : public ContentSharer::Pimpl, : owner (cs) { static PopoverDelegateClass cls; - popoverDelegate.reset ([cls.createInstance() init]); + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wobjc-method-access") + popoverDelegate.reset ([cls.createInstance() initWithContentSharerNativeImpl:this]); + JUCE_END_IGNORE_WARNINGS_GCC_LIKE } ~ContentSharerNativeImpl() override @@ -161,13 +163,9 @@ class ContentSharer::ContentSharerNativeImpl : public ContentSharer::Pimpl, if (isIPad()) { - controller.get().preferredContentSize = peer->view.frame.size; - - auto bounds = peer->view.bounds; - auto* popoverController = controller.get().popoverPresentationController; popoverController.sourceView = peer->view; - popoverController.sourceRect = CGRectMake (0.f, bounds.size.height - 10.f, bounds.size.width, 10.f); + popoverController.sourceRect = getPopoverSourceRect(); popoverController.canOverlapSourceViewRect = YES; popoverController.delegate = popoverDelegate.get(); } @@ -177,25 +175,41 @@ class ContentSharer::ContentSharerNativeImpl : public ContentSharer::Pimpl, } } + CGRect getPopoverSourceRect() { + auto bounds = peer->view.bounds; + + return owner.sourceComponent == nullptr + ? CGRectMake (0.f, bounds.size.height - 10.f, bounds.size.width, 10.f) + : makeCGRect (peer->getAreaCoveredBy (*owner.sourceComponent.getComponent())); + } + //============================================================================== struct PopoverDelegateClass : public ObjCClass> { - PopoverDelegateClass() : ObjCClass> ("PopoverDelegateClass_") + PopoverDelegateClass() : ObjCClass> ("PopoverDelegateClass_") { + addIvar("nativeSharer"); + + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector") + addMethod (@selector (initWithContentSharerNativeImpl:), initWithContentSharerNativeImpl, "@@:^v"); + JUCE_END_IGNORE_WARNINGS_GCC_LIKE + addMethod (@selector (popoverPresentationController:willRepositionPopoverToRect:inView:), willRepositionPopover, "v@:@@@"); registerClass(); } - //============================================================================== - static void willRepositionPopover (id, SEL, UIPopoverPresentationController*, CGRect* rect, UIView*) + static id initWithContentSharerNativeImpl (id _self, SEL, ContentSharer::ContentSharerNativeImpl* nativeSharer) { - auto screenBounds = [UIScreen mainScreen].bounds; + NSObject* self = sendSuperclassMessage (_self, @selector (init)); + object_setInstanceVariable (self, "nativeSharer", nativeSharer); + return self; + } - rect->origin.x = 0.f; - rect->origin.y = screenBounds.size.height - 10.f; - rect->size.width = screenBounds.size.width; - rect->size.height = 10.f; + //============================================================================== + static void willRepositionPopover (id self, SEL, UIPopoverPresentationController*, CGRect* rect, UIView*) + { + *rect = getIvar (self, "nativeSharer")->getPopoverSourceRect(); } };