diff options
Diffstat (limited to 'layout/xul/nsPopupSetFrame.cpp')
-rw-r--r-- | layout/xul/nsPopupSetFrame.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/layout/xul/nsPopupSetFrame.cpp b/layout/xul/nsPopupSetFrame.cpp new file mode 100644 index 0000000000..0e62401480 --- /dev/null +++ b/layout/xul/nsPopupSetFrame.cpp @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsPopupSetFrame.h" +#include "nsGkAtoms.h" +#include "nsCOMPtr.h" +#include "nsIContent.h" +#include "nsPresContext.h" +#include "mozilla/ComputedStyle.h" +#include "mozilla/PresShell.h" +#include "nsBoxLayoutState.h" +#include "nsIScrollableFrame.h" +#include "nsIPopupContainer.h" +#include "nsMenuPopupFrame.h" + +typedef mozilla::ComputedStyle ComputedStyle; + +nsIFrame* NS_NewPopupSetFrame(mozilla::PresShell* aPresShell, + ComputedStyle* aStyle) { + return new (aPresShell) nsPopupSetFrame(aStyle, aPresShell->GetPresContext()); +} + +NS_IMPL_FRAMEARENA_HELPERS(nsPopupSetFrame) + +void nsPopupSetFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, + nsIFrame* aPrevInFlow) { + nsBoxFrame::Init(aContent, aParent, aPrevInFlow); + + // Normally the root box is our grandparent, but in case of wrapping + // it can be our great-grandparent. + nsIPopupContainer* popupContainer = + nsIPopupContainer::GetPopupContainer(PresContext()->GetPresShell()); + if (popupContainer) { + popupContainer->SetPopupSetFrame(this); + } +} + +void nsPopupSetFrame::AppendFrames(ChildListID aListID, + nsFrameList& aFrameList) { + if (aListID == kPopupList) { + AddPopupFrameList(aFrameList); + return; + } + nsBoxFrame::AppendFrames(aListID, aFrameList); +} + +void nsPopupSetFrame::RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) { + if (aListID == kPopupList) { + RemovePopupFrame(aOldFrame); + return; + } + nsBoxFrame::RemoveFrame(aListID, aOldFrame); +} + +void nsPopupSetFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, + const nsLineList::iterator* aPrevFrameLine, + nsFrameList& aFrameList) { + if (aListID == kPopupList) { + AddPopupFrameList(aFrameList); + return; + } + nsBoxFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine, aFrameList); +} + +void nsPopupSetFrame::SetInitialChildList(ChildListID aListID, + nsFrameList& aChildList) { + if (aListID == kPopupList) { + NS_ASSERTION(mPopupList.IsEmpty(), + "SetInitialChildList on non-empty child list"); + AddPopupFrameList(aChildList); + return; + } + nsBoxFrame::SetInitialChildList(aListID, aChildList); +} + +const nsFrameList& nsPopupSetFrame::GetChildList(ChildListID aListID) const { + if (kPopupList == aListID) { + return mPopupList; + } + return nsBoxFrame::GetChildList(aListID); +} + +void nsPopupSetFrame::GetChildLists(nsTArray<ChildList>* aLists) const { + nsBoxFrame::GetChildLists(aLists); + mPopupList.AppendIfNonempty(aLists, kPopupList); +} + +void nsPopupSetFrame::DestroyFrom(nsIFrame* aDestructRoot, + PostDestroyData& aPostDestroyData) { + mPopupList.DestroyFramesFrom(aDestructRoot, aPostDestroyData); + + // Normally the root box is our grandparent, but in case of wrapping + // it can be our great-grandparent. + nsIPopupContainer* popupContainer = + nsIPopupContainer::GetPopupContainer(PresContext()->GetPresShell()); + if (popupContainer) { + popupContainer->SetPopupSetFrame(nullptr); + } + + nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData); +} + +NS_IMETHODIMP +nsPopupSetFrame::DoXULLayout(nsBoxLayoutState& aState) { + // lay us out + nsresult rv = nsBoxFrame::DoXULLayout(aState); + + // lay out all of our currently open popups. + for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) { + nsMenuPopupFrame* popupChild = static_cast<nsMenuPopupFrame*>(e.get()); + popupChild->LayoutPopup(aState, nullptr, false); + } + + return rv; +} + +void nsPopupSetFrame::RemovePopupFrame(nsIFrame* aPopup) { + MOZ_ASSERT(aPopup->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) && + aPopup->IsMenuPopupFrame(), + "removing wrong type of frame in popupset's ::popupList"); + + mPopupList.DestroyFrame(aPopup); +} + +void nsPopupSetFrame::AddPopupFrameList(nsFrameList& aPopupFrameList) { +#ifdef DEBUG + for (nsFrameList::Enumerator e(aPopupFrameList); !e.AtEnd(); e.Next()) { + NS_ASSERTION(e.get()->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) && + e.get()->IsMenuPopupFrame(), + "adding wrong type of frame in popupset's ::popupList"); + } +#endif + mPopupList.InsertFrames(nullptr, nullptr, aPopupFrameList); +} |