123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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 "nsHTMLParts.h"
- #include "nsStyleConsts.h"
- #include "nsGkAtoms.h"
- #include "nsIPresShell.h"
- #include "nsBoxFrame.h"
- #include "nsDisplayList.h"
- #include "nsStackLayout.h"
- #include "nsIRootBox.h"
- #include "nsIContent.h"
- #include "nsXULTooltipListener.h"
- #include "nsFrameManager.h"
- #include "mozilla/BasicEvents.h"
- using namespace mozilla;
- // Interface IDs
- //#define DEBUG_REFLOW
- // static
- nsIRootBox*
- nsIRootBox::GetRootBox(nsIPresShell* aShell)
- {
- if (!aShell) {
- return nullptr;
- }
- nsIFrame* rootFrame = aShell->FrameManager()->GetRootFrame();
- if (!rootFrame) {
- return nullptr;
- }
- if (rootFrame) {
- rootFrame = rootFrame->PrincipalChildList().FirstChild();
- }
- nsIRootBox* rootBox = do_QueryFrame(rootFrame);
- return rootBox;
- }
- class nsRootBoxFrame : public nsBoxFrame, public nsIRootBox {
- public:
- friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
- explicit nsRootBoxFrame(nsStyleContext* aContext);
- NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
- virtual nsPopupSetFrame* GetPopupSetFrame() override;
- virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) override;
- virtual nsIContent* GetDefaultTooltip() override;
- virtual void SetDefaultTooltip(nsIContent* aTooltip) override;
- virtual nsresult AddTooltipSupport(nsIContent* aNode) override;
- virtual nsresult RemoveTooltipSupport(nsIContent* aNode) override;
- virtual void AppendFrames(ChildListID aListID,
- nsFrameList& aFrameList) override;
- virtual void InsertFrames(ChildListID aListID,
- nsIFrame* aPrevFrame,
- nsFrameList& aFrameList) override;
- virtual void RemoveFrame(ChildListID aListID,
- nsIFrame* aOldFrame) override;
- virtual void Reflow(nsPresContext* aPresContext,
- ReflowOutput& aDesiredSize,
- const ReflowInput& aReflowInput,
- nsReflowStatus& aStatus) override;
- virtual nsresult HandleEvent(nsPresContext* aPresContext,
- WidgetGUIEvent* aEvent,
- nsEventStatus* aEventStatus) override;
- virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists) override;
- /**
- * Get the "type" of the frame
- *
- * @see nsGkAtoms::rootFrame
- */
- virtual nsIAtom* GetType() const override;
- virtual bool IsFrameOfType(uint32_t aFlags) const override
- {
- // Override bogus IsFrameOfType in nsBoxFrame.
- if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
- return false;
- return nsBoxFrame::IsFrameOfType(aFlags);
- }
-
- #ifdef DEBUG_FRAME_DUMP
- virtual nsresult GetFrameName(nsAString& aResult) const override;
- #endif
- nsPopupSetFrame* mPopupSetFrame;
- protected:
- nsIContent* mDefaultTooltip;
- };
- //----------------------------------------------------------------------
- nsContainerFrame*
- NS_NewRootBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
- {
- return new (aPresShell) nsRootBoxFrame(aContext);
- }
- NS_IMPL_FRAMEARENA_HELPERS(nsRootBoxFrame)
- nsRootBoxFrame::nsRootBoxFrame(nsStyleContext* aContext):
- nsBoxFrame(aContext, true)
- {
- mPopupSetFrame = nullptr;
- nsCOMPtr<nsBoxLayout> layout;
- NS_NewStackLayout(layout);
- SetXULLayoutManager(layout);
- }
- void
- nsRootBoxFrame::AppendFrames(ChildListID aListID,
- nsFrameList& aFrameList)
- {
- MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list ID");
- MOZ_ASSERT(mFrames.IsEmpty(), "already have a child frame");
- nsBoxFrame::AppendFrames(aListID, aFrameList);
- }
- void
- nsRootBoxFrame::InsertFrames(ChildListID aListID,
- nsIFrame* aPrevFrame,
- nsFrameList& aFrameList)
- {
- // Because we only support a single child frame inserting is the same
- // as appending.
- MOZ_ASSERT(!aPrevFrame, "unexpected previous sibling frame");
- AppendFrames(aListID, aFrameList);
- }
- void
- nsRootBoxFrame::RemoveFrame(ChildListID aListID,
- nsIFrame* aOldFrame)
- {
- NS_ASSERTION(aListID == kPrincipalList, "unexpected child list ID");
- if (aOldFrame == mFrames.FirstChild()) {
- nsBoxFrame::RemoveFrame(aListID, aOldFrame);
- } else {
- MOZ_CRASH("unknown aOldFrame");
- }
- }
- #ifdef DEBUG_REFLOW
- int32_t gReflows = 0;
- #endif
- void
- nsRootBoxFrame::Reflow(nsPresContext* aPresContext,
- ReflowOutput& aDesiredSize,
- const ReflowInput& aReflowInput,
- nsReflowStatus& aStatus)
- {
- DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame");
- #ifdef DEBUG_REFLOW
- gReflows++;
- printf("----Reflow %d----\n", gReflows);
- #endif
- return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
- }
- void
- nsRootBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists)
- {
- if (mContent && mContent->GetProperty(nsGkAtoms::DisplayPortMargins)) {
- // The XUL document's root element may have displayport margins set in
- // ChromeProcessController::InitializeRoot, and we should to supply the
- // base rect.
- nsRect displayPortBase =
- aBuilder->GetDirtyRect().Intersect(nsRect(nsPoint(0, 0), GetSize()));
- nsLayoutUtils::SetDisplayPortBase(mContent, displayPortBase);
- }
- // root boxes don't need a debug border/outline or a selection overlay...
- // They *may* have a background propagated to them, so force creation
- // of a background display list element.
- DisplayBorderBackgroundOutline(aBuilder, aLists, true);
- BuildDisplayListForChildren(aBuilder, aLists);
- }
- nsresult
- nsRootBoxFrame::HandleEvent(nsPresContext* aPresContext,
- WidgetGUIEvent* aEvent,
- nsEventStatus* aEventStatus)
- {
- NS_ENSURE_ARG_POINTER(aEventStatus);
- if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
- return NS_OK;
- }
- if (aEvent->mMessage == eMouseUp) {
- nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
- }
- return NS_OK;
- }
- // REVIEW: The override here was doing nothing since nsBoxFrame is our
- // parent class
- nsIAtom*
- nsRootBoxFrame::GetType() const
- {
- return nsGkAtoms::rootFrame;
- }
- nsPopupSetFrame*
- nsRootBoxFrame::GetPopupSetFrame()
- {
- return mPopupSetFrame;
- }
- void
- nsRootBoxFrame::SetPopupSetFrame(nsPopupSetFrame* aPopupSet)
- {
- // Under normal conditions this should only be called once. However,
- // if something triggers ReconstructDocElementHierarchy, we will
- // destroy this frame's child (the nsDocElementBoxFrame), but not this
- // frame. This will cause the popupset to remove itself by calling
- // |SetPopupSetFrame(nullptr)|, and then we'll be able to accept a new
- // popupset. Since the anonymous content is associated with the
- // nsDocElementBoxFrame, we'll get a new popupset when the new doc
- // element box frame is created.
- if (!mPopupSetFrame || !aPopupSet) {
- mPopupSetFrame = aPopupSet;
- } else {
- NS_NOTREACHED("Popup set is already defined! Only 1 allowed.");
- }
- }
- nsIContent*
- nsRootBoxFrame::GetDefaultTooltip()
- {
- return mDefaultTooltip;
- }
- void
- nsRootBoxFrame::SetDefaultTooltip(nsIContent* aTooltip)
- {
- mDefaultTooltip = aTooltip;
- }
- nsresult
- nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode)
- {
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
- nsXULTooltipListener *listener = nsXULTooltipListener::GetInstance();
- if (!listener)
- return NS_ERROR_OUT_OF_MEMORY;
- return listener->AddTooltipSupport(aNode);
- }
- nsresult
- nsRootBoxFrame::RemoveTooltipSupport(nsIContent* aNode)
- {
- // XXjh yuck, I'll have to implement a way to get at
- // the tooltip listener for a given node to make
- // this work. Not crucial, we aren't removing
- // tooltips from any nodes in the app just yet.
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- NS_QUERYFRAME_HEAD(nsRootBoxFrame)
- NS_QUERYFRAME_ENTRY(nsIRootBox)
- NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
- #ifdef DEBUG_FRAME_DUMP
- nsresult
- nsRootBoxFrame::GetFrameName(nsAString& aResult) const
- {
- return MakeFrameName(NS_LITERAL_STRING("RootBox"), aResult);
- }
- #endif
|