mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 333481. Sort table-part event-handling display items to ensure that the table comes before all row-groups, which come before all rows, which come before all cells. r=bernd
This commit is contained in:
parent
e93572b185
commit
ee089f28b9
@ -228,10 +228,8 @@ nsIFrame* nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) co
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
typedef PRBool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
||||
void* aClosure);
|
||||
|
||||
static void Sort(nsDisplayList* aList, PRInt32 aCount, SortLEQ aCmp, void* aClosure) {
|
||||
static void Sort(nsDisplayList* aList, PRInt32 aCount, nsDisplayList::SortLEQ aCmp,
|
||||
void* aClosure) {
|
||||
if (aCount < 2)
|
||||
return;
|
||||
|
||||
@ -326,13 +324,17 @@ void nsDisplayList::ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder) {
|
||||
void nsDisplayList::SortByZOrder(nsDisplayListBuilder* aBuilder,
|
||||
nsIContent* aCommonAncestor) {
|
||||
ExplodeAnonymousChildLists(aBuilder);
|
||||
Sort(this, Count(), IsZOrderLEQ, aCommonAncestor);
|
||||
Sort(IsZOrderLEQ, aCommonAncestor);
|
||||
}
|
||||
|
||||
void nsDisplayList::SortByContentOrder(nsDisplayListBuilder* aBuilder,
|
||||
nsIContent* aCommonAncestor) {
|
||||
ExplodeAnonymousChildLists(aBuilder);
|
||||
Sort(this, Count(), IsContentLEQ, aCommonAncestor);
|
||||
Sort(IsContentLEQ, aCommonAncestor);
|
||||
}
|
||||
|
||||
void nsDisplayList::Sort(SortLEQ aCmp, void* aClosure) {
|
||||
::Sort(this, Count(), aCmp, aClosure);
|
||||
}
|
||||
|
||||
static PRBool
|
||||
|
@ -551,6 +551,16 @@ public:
|
||||
*/
|
||||
void SortByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
|
||||
|
||||
/**
|
||||
* Generic stable sort. Take care, because some of the items might be nsDisplayLists
|
||||
* themselves.
|
||||
* aCmp(item1, item2) should return true if item1 <= item2. We sort the items
|
||||
* into increasing order.
|
||||
*/
|
||||
typedef PRBool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
||||
void* aClosure);
|
||||
void Sort(SortLEQ aCmp, void* aClosure);
|
||||
|
||||
/**
|
||||
* Optimize the display list for visibility, removing any elements that
|
||||
* are not visible. We put this logic here so it can be shared by top-level
|
||||
|
@ -1379,18 +1379,45 @@ nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
aBuilder->ToReferenceFrame(mFrame));
|
||||
}
|
||||
|
||||
static PRInt32 GetTablePartRank(nsDisplayItem* aItem)
|
||||
{
|
||||
nsIAtom* type = aItem->GetUnderlyingFrame()->GetType();
|
||||
if (type == nsGkAtoms::tableFrame)
|
||||
return 0;
|
||||
if (type == nsGkAtoms::tableRowGroupFrame)
|
||||
return 1;
|
||||
if (type == nsGkAtoms::tableRowFrame)
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
static PRBool CompareByTablePartRank(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
||||
void* aClosure)
|
||||
{
|
||||
return GetTablePartRank(aItem1) <= GetTablePartRank(aItem2);
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||
nsFrame* aFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists)
|
||||
const nsDisplayListSet& aLists,
|
||||
PRBool aIsRoot)
|
||||
{
|
||||
nsDisplayList eventsBorderBackground;
|
||||
// If we need to sort the event backgrounds, then we'll put descendant
|
||||
// border-backgrounds into their own list so we don't accidentally sort
|
||||
// some ancestor's border-background.
|
||||
PRBool sortEventBackgrounds = aIsRoot && aBuilder->IsForEventDelivery();
|
||||
nsDisplayListSet lists(aLists,
|
||||
sortEventBackgrounds ? &eventsBorderBackground : aLists.BorderBackground());
|
||||
|
||||
// Create dedicated background display items per-frame when we're
|
||||
// handling events.
|
||||
// XXX how to handle collapsed borders?
|
||||
if (aBuilder->IsForEventDelivery() &&
|
||||
aFrame->IsVisibleForPainting(aBuilder)) {
|
||||
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
||||
nsresult rv = lists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayBackground(aFrame));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -1405,12 +1432,20 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||
// lets us get cell borders into the nsTableFrame's BorderBackground list.
|
||||
nsIFrame* kid = aFrame->GetFirstChild(nsnull);
|
||||
while (kid) {
|
||||
nsresult rv = aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
|
||||
nsresult rv = aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, lists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
|
||||
return aFrame->DisplayOutline(aBuilder, aLists);
|
||||
if (sortEventBackgrounds) {
|
||||
// Ensure that the table frame event background goes before the
|
||||
// table rowgroups event backgrounds, before the table row event backgrounds,
|
||||
// before everything else (cells and their blocks)
|
||||
eventsBorderBackground.Sort(CompareByTablePartRank, nsnull);
|
||||
aLists.BorderBackground()->AppendToTop(&eventsBorderBackground);
|
||||
}
|
||||
|
||||
return aFrame->DisplayOutline(aBuilder, lists);
|
||||
}
|
||||
|
||||
// table paint code is concerned primarily with borders and bg color
|
||||
@ -1430,7 +1465,7 @@ nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayTableBorderBackground(this));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
|
||||
return DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, PR_TRUE);
|
||||
}
|
||||
|
||||
// XXX We don't put the borders and backgrounds in tree order like we should.
|
||||
|
@ -263,11 +263,14 @@ public:
|
||||
* and row frames. It creates a background display item for handling events
|
||||
* if necessary, an outline display item if necessary, and displays
|
||||
* all the the frame's children.
|
||||
* @param aIsRoot true if aFrame is the table frame or a table part which
|
||||
* happens to be the root of a stacking context
|
||||
*/
|
||||
static nsresult DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||
nsFrame* aFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
nsFrame* aFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists,
|
||||
PRBool aIsRoot);
|
||||
|
||||
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
|
||||
// of type aChildType.
|
||||
|
@ -582,7 +582,6 @@ nsDisplayTableRowBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
|
||||
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(mFrame);
|
||||
|
||||
|
||||
nsPoint pt = aBuilder->ToReferenceFrame(mFrame);
|
||||
nsIRenderingContext::AutoPushTranslation translate(aCtx, pt.x, pt.y);
|
||||
TableBackgroundPainter painter(tableFrame,
|
||||
@ -600,7 +599,8 @@ nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
if (!IsVisibleInSelection(aBuilder))
|
||||
return NS_OK;
|
||||
|
||||
if (aBuilder->IsAtRootOfPseudoStackingContext()) {
|
||||
PRBool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
|
||||
if (isRoot) {
|
||||
// This background is created regardless of whether this frame is
|
||||
// visible or not. Visibility decisions are delegated to the
|
||||
// table background painter.
|
||||
@ -612,7 +612,7 @@ nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
|
||||
return nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, isRoot);
|
||||
}
|
||||
|
||||
PRIntn
|
||||
|
@ -210,7 +210,8 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
if (!IsVisibleInSelection(aBuilder))
|
||||
return NS_OK;
|
||||
|
||||
if (aBuilder->IsAtRootOfPseudoStackingContext()) {
|
||||
PRBool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
|
||||
if (isRoot) {
|
||||
// This background is created regardless of whether this frame is
|
||||
// visible or not. Visibility decisions are delegated to the
|
||||
// table background painter.
|
||||
@ -219,7 +220,7 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
|
||||
return nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, isRoot);
|
||||
}
|
||||
|
||||
PRIntn
|
||||
|
Loading…
Reference in New Issue
Block a user