Bug 1927111 - Add support for ChromeOnly flush: false for GeometryUtils. r=layout-reviewers,webidl,saschanaz,dshin

This will be useful for the front-end to replace
nsIDOMWindowUtils.getBoundsWithoutFlushing(), since I need content box
bounds.

Differential Revision: https://phabricator.services.mozilla.com/D226931
This commit is contained in:
Emilio Cobos Álvarez 2024-10-25 18:21:55 +00:00
parent 9fbce11ad8
commit 94a6ec677c
3 changed files with 67 additions and 63 deletions

View File

@ -11,14 +11,20 @@
*/
enum CSSBoxType { "margin", "border", "padding", "content" };
dictionary BoxQuadOptions {
CSSBoxType box = "border";
GeometryNode relativeTo;
dictionary GeometryUtilsOptions {
[ChromeOnly]
boolean createFramesForSuppressedWhitespace = true;
[ChromeOnly]
boolean flush = true;
};
dictionary ConvertCoordinateOptions {
dictionary BoxQuadOptions : GeometryUtilsOptions {
CSSBoxType box = "border";
GeometryNode relativeTo;
};
dictionary ConvertCoordinateOptions : GeometryUtilsOptions {
CSSBoxType fromBox = "border";
CSSBoxType toBox = "border";
};

View File

@ -36,15 +36,23 @@ enum GeometryNodeType {
};
static nsIFrame* GetFrameForNode(nsINode* aNode, GeometryNodeType aType,
bool aCreateFramesForSuppressedWhitespace) {
Document* doc = aNode->OwnerDoc();
if (aType == GEOMETRY_NODE_TEXT && aCreateFramesForSuppressedWhitespace) {
if (PresShell* presShell = doc->GetPresShell()) {
presShell->FrameConstructor()->EnsureFrameForTextNodeIsCreatedAfterFlush(
static_cast<CharacterData*>(aNode));
}
const GeometryUtilsOptions& aOptions) {
RefPtr<Document> doc = aNode->GetComposedDoc();
if (!doc) {
return nullptr;
}
if (aOptions.mFlush) {
if (aType == GEOMETRY_NODE_TEXT &&
aOptions.mCreateFramesForSuppressedWhitespace) {
if (PresShell* presShell = doc->GetPresShell()) {
presShell->FrameConstructor()
->EnsureFrameForTextNodeIsCreatedAfterFlush(
static_cast<CharacterData*>(aNode));
}
}
doc->FlushPendingNotifications(FlushType::Layout);
}
doc->FlushPendingNotifications(FlushType::Layout);
switch (aType) {
case GEOMETRY_NODE_TEXT:
@ -62,81 +70,73 @@ static nsIFrame* GetFrameForNode(nsINode* aNode, GeometryNodeType aType,
static nsIFrame* GetFrameForGeometryNode(
const Optional<OwningGeometryNode>& aGeometryNode, nsINode* aDefaultNode,
bool aCreateFramesForSuppressedWhitespace) {
const GeometryUtilsOptions& aOptions) {
if (!aGeometryNode.WasPassed()) {
return GetFrameForNode(aDefaultNode->OwnerDoc(), GEOMETRY_NODE_DOCUMENT,
aCreateFramesForSuppressedWhitespace);
aOptions);
}
const OwningGeometryNode& value = aGeometryNode.Value();
if (value.IsElement()) {
return GetFrameForNode(value.GetAsElement(), GEOMETRY_NODE_ELEMENT,
aCreateFramesForSuppressedWhitespace);
aOptions);
}
if (value.IsDocument()) {
return GetFrameForNode(value.GetAsDocument(), GEOMETRY_NODE_DOCUMENT,
aCreateFramesForSuppressedWhitespace);
aOptions);
}
return GetFrameForNode(value.GetAsText(), GEOMETRY_NODE_TEXT,
aCreateFramesForSuppressedWhitespace);
return GetFrameForNode(value.GetAsText(), GEOMETRY_NODE_TEXT, aOptions);
}
static nsIFrame* GetFrameForGeometryNode(const GeometryNode& aGeometryNode) {
// This will create frames for suppressed whitespace nodes.
static nsIFrame* GetFrameForGeometryNode(const GeometryNode& aGeometryNode,
const GeometryUtilsOptions& aOptions) {
if (aGeometryNode.IsElement()) {
return GetFrameForNode(&aGeometryNode.GetAsElement(), GEOMETRY_NODE_ELEMENT,
true);
aOptions);
}
if (aGeometryNode.IsDocument()) {
return GetFrameForNode(&aGeometryNode.GetAsDocument(),
GEOMETRY_NODE_DOCUMENT, true);
GEOMETRY_NODE_DOCUMENT, aOptions);
}
return GetFrameForNode(&aGeometryNode.GetAsText(), GEOMETRY_NODE_TEXT, true);
return GetFrameForNode(&aGeometryNode.GetAsText(), GEOMETRY_NODE_TEXT,
aOptions);
}
static nsIFrame* GetFrameForNode(nsINode* aNode,
bool aCreateFramesForSuppressedWhitespace) {
const GeometryUtilsOptions& aOptions) {
if (aNode->IsElement()) {
return GetFrameForNode(aNode, GEOMETRY_NODE_ELEMENT,
aCreateFramesForSuppressedWhitespace);
return GetFrameForNode(aNode, GEOMETRY_NODE_ELEMENT, aOptions);
}
if (aNode == aNode->OwnerDoc()) {
return GetFrameForNode(aNode, GEOMETRY_NODE_DOCUMENT,
aCreateFramesForSuppressedWhitespace);
return GetFrameForNode(aNode, GEOMETRY_NODE_DOCUMENT, aOptions);
}
NS_ASSERTION(aNode->IsText(), "Unknown node type");
return GetFrameForNode(aNode, GEOMETRY_NODE_TEXT,
aCreateFramesForSuppressedWhitespace);
return GetFrameForNode(aNode, GEOMETRY_NODE_TEXT, aOptions);
}
static nsIFrame* GetFirstNonAnonymousFrameForGeometryNode(
const Optional<OwningGeometryNode>& aNode, nsINode* aDefaultNode,
bool aCreateFramesForSuppressedWhitespace) {
nsIFrame* f = GetFrameForGeometryNode(aNode, aDefaultNode,
aCreateFramesForSuppressedWhitespace);
if (f) {
f = nsLayoutUtils::GetFirstNonAnonymousFrame(f);
const GeometryUtilsOptions& aOptions) {
if (nsIFrame* f = GetFrameForGeometryNode(aNode, aDefaultNode, aOptions)) {
return nsLayoutUtils::GetFirstNonAnonymousFrame(f);
}
return f;
return nullptr;
}
static nsIFrame* GetFirstNonAnonymousFrameForGeometryNode(
const GeometryNode& aNode) {
// This will create frames for suppressed whitespace nodes.
nsIFrame* f = GetFrameForGeometryNode(aNode);
if (f) {
f = nsLayoutUtils::GetFirstNonAnonymousFrame(f);
const GeometryNode& aNode, const GeometryUtilsOptions& aOptions) {
if (nsIFrame* f = GetFrameForGeometryNode(aNode, aOptions)) {
return nsLayoutUtils::GetFirstNonAnonymousFrame(f);
}
return f;
return nullptr;
}
static nsIFrame* GetFirstNonAnonymousFrameForNode(nsINode* aNode) {
// This will create frames for suppressed whitespace nodes.
nsIFrame* f = GetFrameForNode(aNode, true);
if (f) {
f = nsLayoutUtils::GetFirstNonAnonymousFrame(f);
static nsIFrame* GetFirstNonAnonymousFrameForNode(
nsINode* aNode, const GeometryUtilsOptions& aOptions) {
if (nsIFrame* f = GetFrameForNode(aNode, aOptions)) {
return nsLayoutUtils::GetFirstNonAnonymousFrame(f);
}
return f;
return nullptr;
}
/**
@ -178,7 +178,7 @@ static nsRect GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType) {
class AccumulateQuadCallback : public nsLayoutUtils::BoxCallback {
public:
AccumulateQuadCallback(Document* aParentObject,
nsTArray<RefPtr<DOMQuad> >& aResult,
nsTArray<RefPtr<DOMQuad>>& aResult,
nsIFrame* aRelativeToFrame,
const nsPoint& aRelativeToBoxTopLeft,
CSSBoxType aBoxType)
@ -226,7 +226,7 @@ class AccumulateQuadCallback : public nsLayoutUtils::BoxCallback {
}
nsISupports* mParentObject;
nsTArray<RefPtr<DOMQuad> >& mResult;
nsTArray<RefPtr<DOMQuad>>& mResult;
nsIFrame* mRelativeToFrame;
nsPoint mRelativeToBoxTopLeft;
CSSBoxType mBoxType;
@ -262,10 +262,9 @@ static bool CheckFramesInSameTopLevelBrowsingContext(nsIFrame* aFrame1,
}
void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
nsTArray<RefPtr<DOMQuad> >& aResult, CallerType aCallerType,
nsTArray<RefPtr<DOMQuad>>& aResult, CallerType aCallerType,
ErrorResult& aRv) {
nsIFrame* frame =
GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace);
nsIFrame* frame = GetFrameForNode(aNode, aOptions);
if (!frame) {
// No boxes to return
return;
@ -273,14 +272,12 @@ void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
AutoWeakFrame weakFrame(frame);
Document* ownerDoc = aNode->OwnerDoc();
nsIFrame* relativeToFrame = GetFirstNonAnonymousFrameForGeometryNode(
aOptions.mRelativeTo, ownerDoc,
aOptions.mCreateFramesForSuppressedWhitespace);
aOptions.mRelativeTo, ownerDoc, aOptions);
// The first frame might be destroyed now if the above call lead to an
// EnsureFrameForTextNode call. We need to get the first frame again
// when that happens and re-check it.
if (!weakFrame.IsAlive()) {
frame =
GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace);
frame = GetFrameForNode(aNode, aOptions);
if (!frame) {
// No boxes to return
return;
@ -310,7 +307,7 @@ void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
void GetBoxQuadsFromWindowOrigin(nsINode* aNode,
const dom::BoxQuadOptions& aOptions,
nsTArray<RefPtr<DOMQuad> >& aResult,
nsTArray<RefPtr<DOMQuad>>& aResult,
ErrorResult& aRv) {
// We want the quads relative to the window. To do this, we ignore the
// provided aOptions.mRelativeTo and instead use the document node of
@ -395,14 +392,15 @@ static void TransformPoints(nsINode* aTo, const GeometryNode& aFrom,
uint32_t aPointCount, CSSPoint* aPoints,
const ConvertCoordinateOptions& aOptions,
CallerType aCallerType, ErrorResult& aRv) {
nsIFrame* fromFrame = GetFirstNonAnonymousFrameForGeometryNode(aFrom);
nsIFrame* fromFrame =
GetFirstNonAnonymousFrameForGeometryNode(aFrom, aOptions);
AutoWeakFrame weakFrame(fromFrame);
nsIFrame* toFrame = GetFirstNonAnonymousFrameForNode(aTo);
nsIFrame* toFrame = GetFirstNonAnonymousFrameForNode(aTo, aOptions);
// The first frame might be destroyed now if the above call lead to an
// EnsureFrameForTextNode call. We need to get the first frame again
// when that happens.
if (fromFrame && !weakFrame.IsAlive()) {
fromFrame = GetFirstNonAnonymousFrameForGeometryNode(aFrom);
fromFrame = GetFirstNonAnonymousFrameForGeometryNode(aFrom, aOptions);
}
if (!fromFrame || !toFrame) {
aRv.ThrowNotFoundError(

View File

@ -40,12 +40,12 @@ typedef dom::OwningTextOrElementOrDocument OwningGeometryNode;
* GeometryUtils.getBoxQuads. May set an error in aRv.
*/
void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
nsTArray<RefPtr<dom::DOMQuad> >& aResult,
nsTArray<RefPtr<dom::DOMQuad>>& aResult,
dom::CallerType aCallerType, ErrorResult& aRv);
void GetBoxQuadsFromWindowOrigin(nsINode* aNode,
const dom::BoxQuadOptions& aOptions,
nsTArray<RefPtr<dom::DOMQuad> >& aResult,
nsTArray<RefPtr<dom::DOMQuad>>& aResult,
ErrorResult& aRv);
already_AddRefed<dom::DOMQuad> ConvertQuadFromNode(