Bug 1556556 - Add a "relative to layout viewport" option for display list building. r=mstange,mattwoodrow

Use it in document.elementFromPoint().

Differential Revision: https://phabricator.services.mozilla.com/D68914
This commit is contained in:
Botond Ballo 2020-05-05 19:24:08 +00:00
parent 7cf10dca6d
commit 8f18aa54b4
8 changed files with 42 additions and 12 deletions

View File

@ -457,33 +457,41 @@ static void QueryNodesFromPoint(DocumentOrShadowRoot& aRoot, float aX, float aY,
} // namespace
Element* DocumentOrShadowRoot::ElementFromPoint(float aX, float aY) {
return ElementFromPointHelper(aX, aY, false, true);
return ElementFromPointHelper(aX, aY, false, true, true);
}
void DocumentOrShadowRoot::ElementsFromPoint(
float aX, float aY, nsTArray<RefPtr<Element>>& aElements) {
QueryNodesFromPoint(*this, aX, aY, {}, FlushLayout::Yes, Multiple::Yes,
aElements);
QueryNodesFromPoint(*this, aX, aY,
FrameForPointOption::IsRelativeToLayoutViewport,
FlushLayout::Yes, Multiple::Yes, aElements);
}
void DocumentOrShadowRoot::NodesFromPoint(float aX, float aY,
nsTArray<RefPtr<nsINode>>& aNodes) {
QueryNodesFromPoint(*this, aX, aY, {}, FlushLayout::Yes, Multiple::Yes,
aNodes);
QueryNodesFromPoint(*this, aX, aY,
FrameForPointOption::IsRelativeToLayoutViewport,
FlushLayout::Yes, Multiple::Yes, aNodes);
}
nsINode* DocumentOrShadowRoot::NodeFromPoint(float aX, float aY) {
AutoTArray<RefPtr<nsINode>, 1> nodes;
QueryNodesFromPoint(*this, aX, aY, {}, FlushLayout::Yes, Multiple::No, nodes);
QueryNodesFromPoint(*this, aX, aY,
FrameForPointOption::IsRelativeToLayoutViewport,
FlushLayout::Yes, Multiple::No, nodes);
return nodes.SafeElementAt(0);
}
Element* DocumentOrShadowRoot::ElementFromPointHelper(
float aX, float aY, bool aIgnoreRootScrollFrame, bool aFlushLayout) {
float aX, float aY, bool aIgnoreRootScrollFrame, bool aFlushLayout,
bool aIsRelativeToLayoutViewport) {
EnumSet<FrameForPointOption> options;
if (aIgnoreRootScrollFrame) {
options += FrameForPointOption::IgnoreRootScrollFrame;
}
if (aIsRelativeToLayoutViewport) {
options += FrameForPointOption::IsRelativeToLayoutViewport;
}
auto flush = aFlushLayout ? FlushLayout::Yes : FlushLayout::No;

View File

@ -135,7 +135,8 @@ class DocumentOrShadowRoot {
*/
Element* ElementFromPointHelper(float aX, float aY,
bool aIgnoreRootScrollFrame,
bool aFlushLayout);
bool aFlushLayout,
bool aIsRelativeToLayoutViewport);
void NodesFromRect(float aX, float aY, float aTopSize, float aRightSize,
float aBottomSize, float aLeftSize,

View File

@ -1155,8 +1155,8 @@ nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
nsCOMPtr<Document> doc = GetDocument();
NS_ENSURE_STATE(doc);
RefPtr<Element> el =
doc->ElementFromPointHelper(aX, aY, aIgnoreRootScrollFrame, aFlushLayout);
RefPtr<Element> el = doc->ElementFromPointHelper(
aX, aY, aIgnoreRootScrollFrame, aFlushLayout, false);
el.forget(aReturn);
return NS_OK;
}

View File

@ -2648,7 +2648,7 @@ nsresult ContentEventHandler::OnQueryDOMWidgetHittest(
docFrameRect.y);
Element* contentUnderMouse = mDocument->ElementFromPointHelper(
eventLocCSS.x, eventLocCSS.y, false, false);
eventLocCSS.x, eventLocCSS.y, false, false, false);
if (contentUnderMouse) {
nsIWidget* targetWidget = nullptr;
nsIFrame* targetFrame = contentUnderMouse->GetPrimaryFrame();

View File

@ -3187,6 +3187,9 @@ nsresult nsLayoutUtils::GetFramesForArea(
builder.SetIgnoreScrollFrame(rootScrollFrame);
}
}
if (aOptions.contains(FrameForPointOption::IsRelativeToLayoutViewport)) {
builder.SetIsRelativeToLayoutViewport();
}
if (aOptions.contains(FrameForPointOption::IgnoreCrossDoc)) {
builder.SetDescendIntoSubdocuments(false);
}

View File

@ -878,6 +878,12 @@ class nsLayoutUtils {
* When set, return only content that is actually visible.
*/
OnlyVisible,
/**
* When set, coordinates are interpreted as being relative to the layout
* viewport. When not set, coordinates are interpreted as being relative
* to the visual viewport.
*/
IsRelativeToLayoutViewport,
};
/**

View File

@ -1228,6 +1228,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mIsInActiveDocShell(false),
mBuildAsyncZoomContainer(false),
mContainsBackdropFilter(false),
mIsRelativeToLayoutViewport(false),
mHitTestArea(),
mHitTestInfo(CompositorHitTestInvisibleToHit) {
MOZ_COUNT_CTOR(nsDisplayListBuilder);
@ -1450,9 +1451,15 @@ AnimatedGeometryRoot* nsDisplayListBuilder::FindAnimatedGeometryRootFor(
return FindAnimatedGeometryRootFor(aItem->Frame());
}
void nsDisplayListBuilder::SetIsRelativeToLayoutViewport() {
mIsRelativeToLayoutViewport = true;
UpdateShouldBuildAsyncZoomContainer();
}
void nsDisplayListBuilder::UpdateShouldBuildAsyncZoomContainer() {
Document* document = mReferenceFrame->PresContext()->Document();
mBuildAsyncZoomContainer = nsLayoutUtils::AllowZoomingForDocument(document);
mBuildAsyncZoomContainer = !mIsRelativeToLayoutViewport &&
nsLayoutUtils::AllowZoomingForDocument(document);
}
// Certain prefs may cause display list items to be added or removed when they

View File

@ -585,6 +585,10 @@ class nsDisplayListBuilder {
* Get the scrollframe to ignore, if any.
*/
nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
void SetIsRelativeToLayoutViewport();
bool IsRelativeToLayoutViewport() const {
return mIsRelativeToLayoutViewport;
}
/**
* Get the ViewID of the nearest scrolling ancestor frame.
*/
@ -2030,6 +2034,7 @@ class nsDisplayListBuilder {
bool mIsInActiveDocShell;
bool mBuildAsyncZoomContainer;
bool mContainsBackdropFilter;
bool mIsRelativeToLayoutViewport;
nsRect mHitTestArea;
CompositorHitTestInfo mHitTestInfo;