| @@ -470,6 +470,24 @@ struct Component::ComponentHelpers | |||
| for (auto* child : c.childComponentList) | |||
| releaseAllCachedImageResources (*child); | |||
| } | |||
| //============================================================================== | |||
| static bool modalWouldBlockComponent (const Component& maybeBlocked, Component* modal) | |||
| { | |||
| return modal != nullptr | |||
| && modal != &maybeBlocked | |||
| && ! modal->isParentOf (&maybeBlocked) | |||
| && ! modal->canModalEventBeSentToComponent (&maybeBlocked); | |||
| } | |||
| template <typename Function> | |||
| static void sendMouseEventToComponentsThatAreBlockedByModal (Component& modal, Function&& function) | |||
| { | |||
| for (auto& ms : Desktop::getInstance().getMouseSources()) | |||
| if (auto* c = ms.getComponentUnderMouse()) | |||
| if (modalWouldBlockComponent (*c, &modal)) | |||
| (c->*function) (ms, ms.getScreenPosition(), Time::getCurrentTime()); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| @@ -1720,6 +1738,11 @@ void Component::enterModalState (bool shouldTakeKeyboardFocus, | |||
| if (! isCurrentlyModal (false)) | |||
| { | |||
| // While this component is in modal state it may block other components from receiving | |||
| // mouseExit events. To keep mouseEnter and mouseExit calls balanced on these components, | |||
| // we must manually force the mouse to "leave" blocked components. | |||
| ComponentHelpers::sendMouseEventToComponentsThatAreBlockedByModal (*this, &Component::internalMouseExit); | |||
| auto& mcm = *ModalComponentManager::getInstance(); | |||
| mcm.startModal (this, deleteWhenDismissed); | |||
| mcm.attachCallback (this, callback); | |||
| @@ -1746,10 +1769,10 @@ void Component::exitModalState (int returnValue) | |||
| mcm.endModal (this, returnValue); | |||
| mcm.bringModalComponentsToFront(); | |||
| // If any of the mouse sources are over another Component when we exit the modal state then send a mouse enter event | |||
| for (auto& ms : Desktop::getInstance().getMouseSources()) | |||
| if (auto* c = ms.getComponentUnderMouse()) | |||
| c->internalMouseEnter (ms, ms.getScreenPosition(), Time::getCurrentTime()); | |||
| // While this component is in modal state it may block other components from receiving | |||
| // mouseEnter events. To keep mouseEnter and mouseExit calls balanced on these components, | |||
| // we must manually force the mouse to "enter" blocked components. | |||
| ComponentHelpers::sendMouseEventToComponentsThatAreBlockedByModal (*this, &Component::internalMouseEnter); | |||
| } | |||
| else | |||
| { | |||
| @@ -1772,10 +1795,7 @@ bool Component::isCurrentlyModal (bool onlyConsiderForemostModalComponent) const | |||
| bool Component::isCurrentlyBlockedByAnotherModalComponent() const | |||
| { | |||
| auto* mc = getCurrentlyModalComponent(); | |||
| return ! (mc == nullptr || mc == this || mc->isParentOf (this) | |||
| || mc->canModalEventBeSentToComponent (this)); | |||
| return ComponentHelpers::modalWouldBlockComponent (*this, getCurrentlyModalComponent()); | |||
| } | |||
| int JUCE_CALLTYPE Component::getNumCurrentlyModalComponents() noexcept | |||