From 1011b024c474d6becd74244540ebc5daed19c29a Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Tue, 5 May 2020 19:37:26 +0000 Subject: [PATCH] Bug 1556556 - Add some VisualToLayout() and LayoutToVisual() wrappers to ViewportUtils. r=kats Differential Revision: https://phabricator.services.mozilla.com/D68724 --- layout/base/ViewportUtils.cpp | 47 +++++++++++++++++++++++++++++++++++ layout/base/ViewportUtils.h | 17 +++++++++++++ 2 files changed, 64 insertions(+) diff --git a/layout/base/ViewportUtils.cpp b/layout/base/ViewportUtils.cpp index d8f5050ef79d..2e8685d44c34 100644 --- a/layout/base/ViewportUtils.cpp +++ b/layout/base/ViewportUtils.cpp @@ -5,6 +5,7 @@ #include "mozilla/PresShell.h" #include "mozilla/ViewportUtils.h" #include "mozilla/layers/APZCCallbackHelper.h" +#include "mozilla/layers/InputAPZContext.h" #include "mozilla/layers/ScrollableLayerGuid.h" #include "nsIContent.h" #include "nsLayoutUtils.h" @@ -12,6 +13,7 @@ namespace mozilla { using layers::APZCCallbackHelper; +using layers::InputAPZContext; using layers::ScrollableLayerGuid; CSSToCSSMatrix4x4 ViewportUtils::GetVisualToLayoutTransform( @@ -47,4 +49,49 @@ CSSToCSSMatrix4x4 ViewportUtils::GetVisualToLayoutTransform( .PostTranslate(transform.x, transform.y, 0); } +CSSToCSSMatrix4x4 GetVisualToLayoutTransform(PresShell* aContext) { + ScrollableLayerGuid::ViewID targetScrollId = + InputAPZContext::GetTargetLayerGuid().mScrollId; + if (targetScrollId == ScrollableLayerGuid::NULL_SCROLL_ID) { + if (nsIFrame* rootScrollFrame = aContext->GetRootScrollFrame()) { + targetScrollId = + nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent()); + } + } + return ViewportUtils::GetVisualToLayoutTransform(targetScrollId); +} + +nsPoint ViewportUtils::VisualToLayout(const nsPoint& aPt, PresShell* aContext) { + auto visualToLayout = mozilla::GetVisualToLayoutTransform(aContext); + CSSPoint cssPt = CSSPoint::FromAppUnits(aPt); + cssPt = visualToLayout.TransformPoint(cssPt); + return CSSPoint::ToAppUnits(cssPt); +} + +nsRect ViewportUtils::VisualToLayout(const nsRect& aRect, PresShell* aContext) { + auto visualToLayout = mozilla::GetVisualToLayoutTransform(aContext); + CSSRect cssRect = CSSRect::FromAppUnits(aRect); + cssRect = visualToLayout.TransformBounds(cssRect); + nsRect result = CSSRect::ToAppUnits(cssRect); + + // In hit testing codepaths, the input rect often has dimensions of one app + // units. If we are zoomed in enough, the rounded size of the output rect + // can be zero app units, which will fail to Intersect() with anything, and + // therefore cause hit testing to fail. To avoid this, we expand the output + // rect to one app units. + if (!aRect.IsEmpty() && result.IsEmpty()) { + result.width = 1; + result.height = 1; + } + + return result; +} + +nsPoint ViewportUtils::LayoutToVisual(const nsPoint& aPt, PresShell* aContext) { + auto visualToLayout = mozilla::GetVisualToLayoutTransform(aContext); + CSSPoint cssPt = CSSPoint::FromAppUnits(aPt); + auto transformed = visualToLayout.Inverse().TransformPoint(cssPt); + return CSSPoint::ToAppUnits(transformed); +} + } // namespace mozilla \ No newline at end of file diff --git a/layout/base/ViewportUtils.h b/layout/base/ViewportUtils.h index 20e1bf2bd997..8fe2442a277d 100644 --- a/layout/base/ViewportUtils.h +++ b/layout/base/ViewportUtils.h @@ -8,8 +8,12 @@ #include "Units.h" #include "mozilla/layers/ScrollableLayerGuid.h" +class nsIFrame; + namespace mozilla { +class PresShell; + class ViewportUtils { public: /* Return a transform to be applied to the coordinates of input events @@ -32,6 +36,19 @@ class ViewportUtils { documentation for additional details. */ static CSSToCSSMatrix4x4 GetVisualToLayoutTransform( layers::ScrollableLayerGuid::ViewID aScrollId); + + /* The functions below apply GetVisualToLayoutTransform() or its inverse + * to various quantities. + * + * To determine the appropriate scroll id to pass into + * GetVisualToLayoutTransform(), these functions prefer to use the one + * from InputAPZContext::GetTargetLayerGuid() if one is available. + * If one is not available, they use the scroll id of the root scroll + * frame of the pres shell passed in as |aContext| as a fallback. + */ + static nsPoint VisualToLayout(const nsPoint& aPt, PresShell* aContext); + static nsRect VisualToLayout(const nsRect& aRect, PresShell* aContext); + static nsPoint LayoutToVisual(const nsPoint& aPt, PresShell* aContext); }; } // namespace mozilla