summaryrefslogtreecommitdiff
path: root/layout/xul/nsRootBoxFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/xul/nsRootBoxFrame.cpp')
-rw-r--r--layout/xul/nsRootBoxFrame.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/layout/xul/nsRootBoxFrame.cpp b/layout/xul/nsRootBoxFrame.cpp
new file mode 100644
index 0000000000..fe41dce527
--- /dev/null
+++ b/layout/xul/nsRootBoxFrame.cpp
@@ -0,0 +1,291 @@
+/* -*- 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 "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 nsRect& aDirtyRect,
+ 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 nsRect& aDirtyRect,
+ 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 = aDirtyRect.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, aDirtyRect, 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