mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 837242. Part 3. Keep track of what area is exposed to events so that covered frames don't get events. r=roc
This commit is contained in:
parent
14c31d8c29
commit
c6f1c91b0a
@ -204,16 +204,62 @@ ComputeDistanceFromRect(const nsPoint& aPoint, const nsRect& aRect)
|
||||
return float(NS_hypot(dx, dy));
|
||||
}
|
||||
|
||||
static float
|
||||
ComputeDistanceFromRegion(const nsPoint& aPoint, const nsRegion& aRegion)
|
||||
{
|
||||
nsRegionRectIterator iter(aRegion);
|
||||
const nsRect* r;
|
||||
float minDist = -1;
|
||||
while ((r = iter.Next()) != nullptr) {
|
||||
float dist = ComputeDistanceFromRect(aPoint, *r);
|
||||
if (dist < minDist || minDist < 0) {
|
||||
minDist = dist;
|
||||
}
|
||||
}
|
||||
return minDist;
|
||||
}
|
||||
|
||||
// Subtract aRegion from aExposedRegion as long as that doesn't make the
|
||||
// exposed region get too complex or removes a big chunk of the exposed region.
|
||||
static void
|
||||
SubtractFromExposedRegion(nsRegion* aExposedRegion, const nsRegion& aRegion)
|
||||
{
|
||||
if (aRegion.IsEmpty())
|
||||
return;
|
||||
|
||||
nsRegion tmp;
|
||||
tmp.Sub(*aExposedRegion, aRegion);
|
||||
// Don't let *aExposedRegion get too complex, but don't let it fluff out to
|
||||
// its bounds either. Do let aExposedRegion get more complex if by doing so
|
||||
// we reduce its area by at least half.
|
||||
if (tmp.GetNumRects() <= 15 || tmp.Area() <= aExposedRegion->Area()/2) {
|
||||
*aExposedRegion = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static nsIFrame*
|
||||
GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
|
||||
const EventRadiusPrefs* aPrefs, nsIFrame* aRestrictToDescendants,
|
||||
nsTArray<nsIFrame*>& aCandidates)
|
||||
const nsRect& aTargetRect, const EventRadiusPrefs* aPrefs,
|
||||
nsIFrame* aRestrictToDescendants, nsTArray<nsIFrame*>& aCandidates)
|
||||
{
|
||||
nsIFrame* bestTarget = nullptr;
|
||||
// Lower is better; distance is in appunits
|
||||
float bestDistance = 1e6f;
|
||||
nsRegion exposedRegion(aTargetRect);
|
||||
for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
|
||||
nsIFrame* f = aCandidates[i];
|
||||
|
||||
bool preservesAxisAlignedRectangles = false;
|
||||
nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(f,
|
||||
nsRect(nsPoint(0, 0), f->GetSize()), aRoot, &preservesAxisAlignedRectangles);
|
||||
nsRegion region;
|
||||
region.And(exposedRegion, borderBox);
|
||||
if (preservesAxisAlignedRectangles) {
|
||||
// Subtract from the exposed region if we have a transform that won't make
|
||||
// the bounds include a bunch of area that we don't actually cover.
|
||||
SubtractFromExposedRegion(&exposedRegion, region);
|
||||
}
|
||||
|
||||
if (!IsElementClickable(f)) {
|
||||
continue;
|
||||
}
|
||||
@ -226,10 +272,8 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
|
||||
continue;
|
||||
}
|
||||
|
||||
nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(f,
|
||||
nsRect(nsPoint(0, 0), f->GetSize()), aRoot);
|
||||
// distance is in appunits
|
||||
float distance = ComputeDistanceFromRect(aPointRelativeToRootFrame, borderBox);
|
||||
float distance = ComputeDistanceFromRegion(aPointRelativeToRootFrame, region);
|
||||
nsIContent* content = f->GetContent();
|
||||
if (content && content->IsElement() &&
|
||||
content->AsElement()->State().HasState(nsEventStates(NS_EVENT_STATE_VISITED))) {
|
||||
@ -283,7 +327,7 @@ FindFrameTargetedByInputEvent(const nsGUIEvent *aEvent,
|
||||
nsIFrame* restrictToDescendants = target ?
|
||||
target->PresContext()->PresShell()->GetRootFrame() : aRootFrame;
|
||||
nsIFrame* closestClickable =
|
||||
GetClosest(aRootFrame, aPointRelativeToRootFrame, prefs,
|
||||
GetClosest(aRootFrame, aPointRelativeToRootFrame, targetRect, prefs,
|
||||
restrictToDescendants, candidates);
|
||||
return closestClickable ? closestClickable : target;
|
||||
}
|
||||
|
@ -1596,9 +1596,15 @@ TransformGfxRectFromAncestor(nsIFrame *aFrame,
|
||||
static gfxRect
|
||||
TransformGfxRectToAncestor(nsIFrame *aFrame,
|
||||
const gfxRect &aRect,
|
||||
const nsIFrame *aAncestor)
|
||||
const nsIFrame *aAncestor,
|
||||
bool* aPreservesAxisAlignedRectangles = nullptr)
|
||||
{
|
||||
gfx3DMatrix ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
|
||||
if (aPreservesAxisAlignedRectangles) {
|
||||
gfxMatrix matrix2d;
|
||||
*aPreservesAxisAlignedRectangles =
|
||||
ctm.Is2D(&matrix2d) && matrix2d.PreservesAxisAlignedRectangles();
|
||||
}
|
||||
return ctm.TransformBounds(aRect);
|
||||
}
|
||||
|
||||
@ -1666,7 +1672,8 @@ nsLayoutUtils::TransformAncestorRectToFrame(nsIFrame* aFrame,
|
||||
nsRect
|
||||
nsLayoutUtils::TransformFrameRectToAncestor(nsIFrame* aFrame,
|
||||
const nsRect& aRect,
|
||||
const nsIFrame* aAncestor)
|
||||
const nsIFrame* aAncestor,
|
||||
bool* aPreservesAxisAlignedRectangles /* = nullptr */)
|
||||
{
|
||||
nsSVGTextFrame2* text = GetContainingSVGTextFrame(aFrame);
|
||||
|
||||
@ -1676,12 +1683,16 @@ nsLayoutUtils::TransformFrameRectToAncestor(nsIFrame* aFrame,
|
||||
if (text) {
|
||||
result = text->TransformFrameRectFromTextChild(aRect, aFrame);
|
||||
result = TransformGfxRectToAncestor(text, result, aAncestor);
|
||||
// TransformFrameRectFromTextChild could involve any kind of transform, we
|
||||
// could drill down into it to get an answer out of it but we don't yet.
|
||||
if (aPreservesAxisAlignedRectangles)
|
||||
*aPreservesAxisAlignedRectangles = false;
|
||||
} else {
|
||||
result = gfxRect(NSAppUnitsToFloatPixels(aRect.x, srcAppUnitsPerDevPixel),
|
||||
NSAppUnitsToFloatPixels(aRect.y, srcAppUnitsPerDevPixel),
|
||||
NSAppUnitsToFloatPixels(aRect.width, srcAppUnitsPerDevPixel),
|
||||
NSAppUnitsToFloatPixels(aRect.height, srcAppUnitsPerDevPixel));
|
||||
result = TransformGfxRectToAncestor(aFrame, result, aAncestor);
|
||||
result = TransformGfxRectToAncestor(aFrame, result, aAncestor, aPreservesAxisAlignedRectangles);
|
||||
}
|
||||
|
||||
float destAppUnitsPerDevPixel = aAncestor->PresContext()->AppUnitsPerDevPixel();
|
||||
|
@ -572,10 +572,13 @@ public:
|
||||
/**
|
||||
* Transform aRect relative to aFrame up to the coordinate system of
|
||||
* aAncestor. Computes the bounding-box of the true quadrilateral.
|
||||
* Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if
|
||||
* we only need to use a 2d transform that PreservesAxisAlignedRectangles().
|
||||
*/
|
||||
static nsRect TransformFrameRectToAncestor(nsIFrame* aFrame,
|
||||
const nsRect& aRect,
|
||||
const nsIFrame* aAncestor);
|
||||
const nsIFrame* aAncestor,
|
||||
bool* aPreservesAxisAlignedRectangles = nullptr);
|
||||
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user