Browse Source

Component: Ensure that mouseEnter and mouseExit calls are balanced when entering/leaving modal state

v6.1.6
reuk 4 years ago
parent
commit
f85ede6b47
No known key found for this signature in database GPG Key ID: 9ADCD339CFC98A11
1 changed files with 28 additions and 8 deletions
  1. +28
    -8
      modules/juce_gui_basics/components/juce_Component.cpp

+ 28
- 8
modules/juce_gui_basics/components/juce_Component.cpp View File

@@ -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


Loading…
Cancel
Save