mirror of
https://github.com/ManchildProductions/UXP-Fixed.git
synced 2026-05-27 07:20:16 +00:00
cbb61ab832
Part 1: Remove current table item, as it's never set. Part 2: Get rid of generic table painting code, and handle each class separately. Part 4: Hoist outline skipping into col(group) frame code. Part 5: Skip box-shadow for table column and column groups. Part 6: Store column and column group backgrounds separately, and then append them before the rest of the table contents. Part 7: Pass rects in display list coordinates to AppendBackgroundItemsToTop. Part 8: Create column and column group background display items as part of the cell's BuildDisplayList. Part 9: Used cached values instead of calling nsDisplayListBuilder::ToReferenceFrame when possible, since it can be expensive when the requested frame isn't the builder's current frame. Part 10: Make sure we build display items for table parts where only the normal position is visible, since we may need to create background items for ancestors at that position. Part 11: Create an AutoBuildingDisplayList when we create background items for table columns and column groups, so that we initialize the invalidation state correctly.
291 lines
8.3 KiB
C++
291 lines
8.3 KiB
C++
/* -*- 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 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->GetVisibleRect().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
|