1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Added floating-point implementations for some Component hit-testing methods to improve reliability when dealing with scaled Components

This commit is contained in:
ed 2021-06-08 11:22:42 +01:00
parent 399dcd9cc7
commit 550127945d
3 changed files with 30 additions and 12 deletions

View file

@ -1378,14 +1378,19 @@ void Component::getInterceptsMouseClicks (bool& allowsClicksOnThisComponent,
bool Component::contains (Point<int> point)
{
if (ComponentHelpers::hitTest (*this, point))
return containsInternal (point.toFloat());
}
bool Component::containsInternal (Point<float> point)
{
if (ComponentHelpers::hitTest (*this, point.roundToInt()))
{
if (parentComponent != nullptr)
return parentComponent->contains (ComponentHelpers::convertToParentSpace (*this, point));
return parentComponent->containsInternal (ComponentHelpers::convertToParentSpace (*this, point));
if (flags.hasHeavyweightPeerFlag)
if (auto* peer = getPeer())
return peer->contains (ComponentHelpers::localPositionToRawPeerPos (*this, point), true);
return peer->contains (ComponentHelpers::localPositionToRawPeerPos (*this, point).roundToInt(), true);
}
return false;
@ -1393,24 +1398,34 @@ bool Component::contains (Point<int> point)
bool Component::reallyContains (Point<int> point, bool returnTrueIfWithinAChild)
{
if (! contains (point))
return reallyContainsInternal (point.toFloat(), returnTrueIfWithinAChild);
}
bool Component::reallyContainsInternal (Point<float> point, bool returnTrueIfWithinAChild)
{
if (! containsInternal (point))
return false;
auto* top = getTopLevelComponent();
auto* compAtPosition = top->getComponentAt (top->getLocalPoint (this, point));
auto* compAtPosition = top->getComponentAtInternal (top->getLocalPoint (this, point));
return (compAtPosition == this) || (returnTrueIfWithinAChild && isParentOf (compAtPosition));
}
Component* Component::getComponentAt (Point<int> position)
{
if (flags.visibleFlag && ComponentHelpers::hitTest (*this, position))
return getComponentAtInternal (position.toFloat());
}
Component* Component::getComponentAtInternal (Point<float> position)
{
if (flags.visibleFlag && ComponentHelpers::hitTest (*this, position.roundToInt()))
{
for (int i = childComponentList.size(); --i >= 0;)
{
auto* child = childComponentList.getUnchecked(i);
auto* child = childComponentList.getUnchecked (i);
child = child->getComponentAt (ComponentHelpers::convertFromParentSpace (*child, position));
child = child->getComponentAtInternal (ComponentHelpers::convertFromParentSpace (*child, position));
if (child != nullptr)
return child;
@ -3019,7 +3034,7 @@ bool Component::isMouseOver (bool includeChildren) const
if (c != nullptr && (c == this || (includeChildren && isParentOf (c))))
if (ms.isDragging() || ! (ms.isTouch() || ms.isPen()))
if (c->reallyContains (c->getLocalPoint (nullptr, ms.getScreenPosition().roundToInt()), false))
if (c->reallyContainsInternal (c->getLocalPoint (nullptr, ms.getScreenPosition()), false))
return true;
}

View file

@ -2565,6 +2565,10 @@ private:
void sendEnablementChangeMessage();
void sendVisibilityChangeMessage();
bool containsInternal (Point<float>);
bool reallyContainsInternal (Point<float>, bool);
Component* getComponentAtInternal (Point<float>);
struct ComponentHelpers;
friend struct ComponentHelpers;

View file

@ -76,11 +76,10 @@ public:
auto relativePos = ScalingHelpers::unscaledScreenPosToScaled (peer->getComponent(),
peer->globalToLocal (screenPos));
auto& comp = peer->getComponent();
auto pos = relativePos.roundToInt();
// (the contains() call is needed to test for overlapping desktop windows)
if (comp.contains (pos))
return comp.getComponentAt (pos);
if (comp.containsInternal (relativePos))
return comp.getComponentAtInternal (relativePos);
}
return nullptr;