Bug 1821732 - implement auto popover list, r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D172296
This commit is contained in:
Alexander Surkov 2023-03-13 20:18:46 +00:00
parent f60d745bc2
commit 528bbef9b4
4 changed files with 66 additions and 9 deletions

View File

@ -14574,11 +14574,7 @@ void Document::SetFullscreenElement(Element& aElement) {
void Document::TopLayerPush(Element& aElement) { void Document::TopLayerPush(Element& aElement) {
const bool modal = aElement.State().HasState(ElementState::MODAL); const bool modal = aElement.State().HasState(ElementState::MODAL);
auto predictFunc = [&aElement](Element* element) { TopLayerPop(aElement);
return element == &aElement;
};
TopLayerPop(predictFunc);
mTopLayer.AppendElement(do_GetWeakReference(&aElement)); mTopLayer.AppendElement(do_GetWeakReference(&aElement));
NS_ASSERTION(GetTopLayerTop() == &aElement, "Should match"); NS_ASSERTION(GetTopLayerTop() == &aElement, "Should match");
@ -14614,10 +14610,7 @@ void Document::AddModalDialog(HTMLDialogElement& aDialogElement) {
} }
void Document::RemoveModalDialog(HTMLDialogElement& aDialogElement) { void Document::RemoveModalDialog(HTMLDialogElement& aDialogElement) {
auto predicate = [&aDialogElement](Element* element) -> bool { DebugOnly<Element*> removedElement = TopLayerPop(aDialogElement);
return element == &aDialogElement;
};
DebugOnly<Element*> removedElement = TopLayerPop(predicate);
MOZ_ASSERT(removedElement == &aDialogElement); MOZ_ASSERT(removedElement == &aDialogElement);
aDialogElement.RemoveStates(ElementState::MODAL); aDialogElement.RemoveStates(ElementState::MODAL);
} }
@ -14685,6 +14678,13 @@ Element* Document::TopLayerPop(FunctionRef<bool(Element*)> aPredicate) {
return removedElement; return removedElement;
} }
Element* Document::TopLayerPop(Element& aElement) {
auto predictFunc = [&aElement](Element* element) {
return element == &aElement;
};
return TopLayerPop(predictFunc);
}
void Document::GetWireframe(bool aIncludeNodes, void Document::GetWireframe(bool aIncludeNodes,
Nullable<Wireframe>& aWireframe) { Nullable<Wireframe>& aWireframe) {
FlushPendingNotifications(FlushType::Layout); FlushPendingNotifications(FlushType::Layout);
@ -14826,6 +14826,38 @@ nsTArray<Element*> Document::GetTopLayer() const {
return elements; return elements;
} }
nsTArray<Element*> Document::AutoPopoverList() const {
nsTArray<Element*> elements;
for (const nsWeakPtr& ptr : mTopLayer) {
if (nsCOMPtr<Element> element = do_QueryReferent(ptr)) {
if (element && element->IsAutoPopover()) {
elements.AppendElement(element);
}
}
}
return elements;
}
Element* Document::GetTopmostAutoPopover() const {
for (const nsWeakPtr& weakPtr : Reversed(mTopLayer)) {
nsCOMPtr<Element> element(do_QueryReferent(weakPtr));
if (element && element->IsAutoPopover()) {
return element;
}
}
return nullptr;
}
void Document::AddToAutoPopoverList(Element& aElement) {
MOZ_ASSERT(aElement.IsAutoPopover());
TopLayerPush(aElement);
}
void Document::RemoveFromAutoPopoverList(Element& aElement) {
MOZ_ASSERT(aElement.IsAutoPopover());
TopLayerPop(aElement);
}
// Returns true if aDoc is in the focused tab in the active window. // Returns true if aDoc is in the focused tab in the active window.
bool IsInActiveTab(Document* aDoc) { bool IsInActiveTab(Document* aDoc) {
BrowsingContext* bc = aDoc->GetBrowsingContext(); BrowsingContext* bc = aDoc->GetBrowsingContext();

View File

@ -1927,6 +1927,10 @@ class Document : public nsINode,
// layer. The removed element, if any, is returned. // layer. The removed element, if any, is returned.
Element* TopLayerPop(FunctionRef<bool(Element*)> aPredicate); Element* TopLayerPop(FunctionRef<bool(Element*)> aPredicate);
// Removes the given element from the top layer. The removed element, if any,
// is returned.
Element* TopLayerPop(Element&);
MOZ_CAN_RUN_SCRIPT bool TryAutoFocusCandidate(Element& aElement); MOZ_CAN_RUN_SCRIPT bool TryAutoFocusCandidate(Element& aElement);
public: public:
@ -3449,6 +3453,20 @@ class Document : public nsINode,
MOZ_CAN_RUN_SCRIPT void GetWireframe(bool aIncludeNodes, MOZ_CAN_RUN_SCRIPT void GetWireframe(bool aIncludeNodes,
Nullable<Wireframe>&); Nullable<Wireframe>&);
// Returns a list of all the elements in the Document's top layer whose
// popover attribute is in the auto state.
// See https://html.spec.whatwg.org/multipage/popover.html#auto-popover-list
nsTArray<Element*> AutoPopoverList() const;
// Teturn document's auto popover list's last element.
// See
// https://html.spec.whatwg.org/multipage/popover.html#topmost-auto-popover
Element* GetTopmostAutoPopover() const;
// Adds/removes an element to/from the auto popover list.
void AddToAutoPopoverList(Element&);
void RemoveFromAutoPopoverList(Element&);
Element* GetTopLayerTop(); Element* GetTopLayerTop();
// Return the fullscreen element in the top layer // Return the fullscreen element in the top layer
Element* GetUnretargetedFullscreenElement() const; Element* GetUnretargetedFullscreenElement() const;

View File

@ -4205,6 +4205,11 @@ void Element::ClearServoData(Document* aDoc) {
} }
} }
bool Element::IsAutoPopover() const {
const auto* htmlElement = nsGenericHTMLElement::FromNode(this);
return htmlElement && htmlElement->GetPopoverState() == PopoverState::Auto;
}
ElementAnimationData& Element::CreateAnimationData() { ElementAnimationData& Element::CreateAnimationData() {
MOZ_ASSERT(!GetAnimationData()); MOZ_ASSERT(!GetAnimationData());
SetMayHaveAnimations(); SetMayHaveAnimations();

View File

@ -580,6 +580,8 @@ class Element : public FragmentOrElement {
return CreatePopoverData(); return CreatePopoverData();
} }
bool IsAutoPopover() const;
ElementAnimationData* GetAnimationData() const { ElementAnimationData* GetAnimationData() const {
if (!MayHaveAnimations()) { if (!MayHaveAnimations()) {
return nullptr; return nullptr;