mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 539356 - Part 9b - Add new frame invalidation API. r=roc
This commit is contained in:
parent
c900597192
commit
cc33f42c8a
@ -1017,6 +1017,8 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsRefPtr<ContainerLayer> root = layerBuilder->
|
||||
BuildContainerLayerFor(aBuilder, layerManager, aForFrame, nullptr, *this,
|
||||
containerParameters, nullptr);
|
||||
|
||||
aForFrame->ClearInvalidationStateBits();
|
||||
|
||||
if (!root) {
|
||||
layerManager->RemoveUserData(&gLayerManagerLayerBuilder);
|
||||
|
@ -4001,6 +4001,8 @@ nsLayoutUtils::IsPopup(nsIFrame* aFrame)
|
||||
/* static */ nsIFrame*
|
||||
nsLayoutUtils::GetDisplayRootFrame(nsIFrame* aFrame)
|
||||
{
|
||||
// We could use GetRootPresContext() here if the
|
||||
// NS_FRAME_IN_POPUP frame bit is set.
|
||||
nsIFrame* f = aFrame;
|
||||
for (;;) {
|
||||
if (IsPopup(f))
|
||||
|
@ -1000,6 +1000,8 @@ nsListControlFrame::Init(nsIContent* aContent,
|
||||
|
||||
mLastDropdownBackstopColor = PresContext()->DefaultBackgroundColor();
|
||||
|
||||
AddStateBits(NS_FRAME_IN_POPUP);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,7 @@
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "nsRenderingContext.h"
|
||||
@ -504,7 +505,8 @@ nsFrame::Init(nsIContent* aContent,
|
||||
// Make bits that are currently off (see constructor) the same:
|
||||
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
|
||||
NS_FRAME_GENERATED_CONTENT |
|
||||
NS_FRAME_IS_SVG_TEXT);
|
||||
NS_FRAME_IS_SVG_TEXT |
|
||||
NS_FRAME_IN_POPUP);
|
||||
}
|
||||
const nsStyleDisplay *disp = GetStyleDisplay();
|
||||
if (disp->HasTransform()) {
|
||||
@ -1268,6 +1270,23 @@ nsFrame::GetChildLists(nsTArray<ChildList>* aLists) const
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::GetCrossDocChildLists(nsTArray<ChildList>* aLists)
|
||||
{
|
||||
nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(this);
|
||||
if (subdocumentFrame) {
|
||||
// Descend into the subdocument
|
||||
nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame();
|
||||
if (root) {
|
||||
aLists->AppendElement(nsIFrame::ChildList(
|
||||
nsFrameList(root, nsLayoutUtils::GetLastSibling(root)),
|
||||
nsIFrame::kPrincipalList));
|
||||
}
|
||||
}
|
||||
|
||||
GetChildLists(aLists);
|
||||
}
|
||||
|
||||
static nsIFrame*
|
||||
GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
|
||||
{
|
||||
@ -4906,10 +4925,60 @@ nsIFrame::InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2)
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateFrameSubtree()
|
||||
nsIFrame::InvalidateFrameSubtree(uint32_t aFlags)
|
||||
{
|
||||
Invalidate(GetVisualOverflowRectRelativeToSelf());
|
||||
FrameLayerBuilder::InvalidateThebesLayersInSubtree(this);
|
||||
InvalidateFrame(aFlags);
|
||||
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
childFrames.get()->
|
||||
InvalidateFrameSubtree(aFlags | INVALIDATE_DONT_SCHEDULE_PAINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::ClearInvalidationStateBits()
|
||||
{
|
||||
if (HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
childFrames.get()->ClearInvalidationStateBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoveStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateFrame(uint32_t aFlags)
|
||||
{
|
||||
AddStateBits(NS_FRAME_NEEDS_PAINT);
|
||||
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(this);
|
||||
while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
|
||||
parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
|
||||
}
|
||||
if (!(aFlags & INVALIDATE_DONT_SCHEDULE_PAINT)) {
|
||||
SchedulePaint();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::IsInvalid()
|
||||
{
|
||||
return HasAnyStateBits(NS_FRAME_NEEDS_PAINT);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4918,6 +4987,36 @@ nsIFrame::InvalidateOverflowRect()
|
||||
Invalidate(GetVisualOverflowRectRelativeToSelf());
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::SchedulePaint()
|
||||
{
|
||||
nsPresContext *pres = PresContext()->GetRootPresContext();
|
||||
if (HasAnyStateBits(NS_FRAME_IN_POPUP) || !pres) {
|
||||
nsIFrame *displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
|
||||
NS_ASSERTION(displayRoot, "Need a display root to schedule a paint!");
|
||||
if (!displayRoot) {
|
||||
return;
|
||||
}
|
||||
pres = displayRoot->PresContext();
|
||||
}
|
||||
pres->PresShell()->ScheduleViewManagerFlush();
|
||||
}
|
||||
|
||||
Layer*
|
||||
nsIFrame::InvalidateLayer(const nsRect& aDamageRect, uint32_t aDisplayItemKey)
|
||||
{
|
||||
NS_ASSERTION(aDisplayItemKey > 0, "Need a key");
|
||||
|
||||
Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey);
|
||||
if (!layer) {
|
||||
InvalidateFrame();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SchedulePaint();
|
||||
return layer;
|
||||
}
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(DeferInvalidatesProperty, nsIFrame::DestroyRegion)
|
||||
|
||||
void
|
||||
@ -8147,6 +8246,55 @@ nsFrame::BoxMetrics() const
|
||||
return metrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the NS_FRAME_IN_POPUP state bit to the current frame,
|
||||
* and all descendant frames (including cross-doc ones).
|
||||
*/
|
||||
static void
|
||||
AddInPopupStateBitToDescendants(nsIFrame* aFrame)
|
||||
{
|
||||
aFrame->AddStateBits(NS_FRAME_IN_POPUP);
|
||||
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
aFrame->GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
AddInPopupStateBitToDescendants(childFrames.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the NS_FRAME_IN_POPUP state bit from the current
|
||||
* frames and all descendant frames (including cross-doc ones),
|
||||
* unless the frame is a popup itself.
|
||||
*/
|
||||
static void
|
||||
RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame)
|
||||
{
|
||||
if (!aFrame->HasAnyStateBits(NS_FRAME_IN_POPUP) ||
|
||||
aFrame->GetType() == nsGkAtoms::listControlFrame ||
|
||||
aFrame->GetType() == nsGkAtoms::menuPopupFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
aFrame->RemoveStateBits(NS_FRAME_IN_POPUP);
|
||||
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
aFrame->GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
RemoveInPopupStateBitFromDescendants(childFrames.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrame::SetParent(nsIFrame* aParent)
|
||||
{
|
||||
@ -8165,6 +8313,20 @@ nsFrame::SetParent(nsIFrame* aParent)
|
||||
f->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
|
||||
}
|
||||
}
|
||||
|
||||
if (HasInvalidFrameInSubtree()) {
|
||||
for (nsIFrame* f = aParent;
|
||||
f && !f->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
f->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
}
|
||||
}
|
||||
|
||||
if (aParent->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
|
||||
AddInPopupStateBitToDescendants(this);
|
||||
} else {
|
||||
RemoveInPopupStateBitFromDescendants(this);
|
||||
}
|
||||
|
||||
if (GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT) {
|
||||
for (nsIFrame* f = aParent;
|
||||
|
@ -311,6 +311,16 @@ typedef uint64_t nsFrameState;
|
||||
// text layout.
|
||||
#define NS_FRAME_IS_SVG_TEXT NS_FRAME_STATE_BIT(47)
|
||||
|
||||
// Frame is marked as needing painting
|
||||
#define NS_FRAME_NEEDS_PAINT NS_FRAME_STATE_BIT(48)
|
||||
|
||||
// Frame has a descendant frame that needs painting - This includes
|
||||
// cross-doc children.
|
||||
#define NS_FRAME_DESCENDANT_NEEDS_PAINT NS_FRAME_STATE_BIT(49)
|
||||
|
||||
// Frame is a descendant of a popup
|
||||
#define NS_FRAME_IN_POPUP NS_FRAME_STATE_BIT(50)
|
||||
|
||||
// Box layout bits
|
||||
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
|
||||
#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)
|
||||
@ -1076,6 +1086,13 @@ public:
|
||||
virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
|
||||
const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); }
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
|
||||
|
||||
/**
|
||||
* Gets the child lists for this frame, including
|
||||
* ones belong to a child document.
|
||||
*/
|
||||
void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
|
||||
|
||||
// XXXbz this method should go away
|
||||
nsIFrame* GetFirstChild(ChildListID aListID) const {
|
||||
return GetChildList(aListID).FirstChild();
|
||||
@ -1399,6 +1416,16 @@ public:
|
||||
void AddStateBits(nsFrameState aBits) { mState |= aBits; }
|
||||
void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
|
||||
|
||||
/**
|
||||
* Checks if the current frame-state includes all of the listed bits
|
||||
*/
|
||||
bool HasAllStateBits(nsFrameState aBits) { return (mState & aBits) == aBits; }
|
||||
|
||||
/**
|
||||
* Checks if the current frame-state includes any of the listed bits
|
||||
*/
|
||||
bool HasAnyStateBits(nsFrameState aBits) { return mState & aBits; }
|
||||
|
||||
/**
|
||||
* This call is invoked on the primary frame for a character data content
|
||||
* node, when it is changed in the content tree.
|
||||
@ -2268,13 +2295,6 @@ public:
|
||||
*/
|
||||
void InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2);
|
||||
|
||||
/**
|
||||
* Invalidate the entire frame subtree for this frame. Invalidates this
|
||||
* frame's overflow rect, and also ensures that all ThebesLayer children
|
||||
* of ContainerLayers associated with frames in this subtree are
|
||||
* completely invalidated.
|
||||
*/
|
||||
void InvalidateFrameSubtree();
|
||||
|
||||
/**
|
||||
* Invalidates this frame's visual overflow rect. Does not necessarily
|
||||
@ -2283,6 +2303,73 @@ public:
|
||||
*/
|
||||
void InvalidateOverflowRect();
|
||||
|
||||
/**
|
||||
* Marks all display items created by this frame as needing a repaint,
|
||||
* and calls SchedulePaint() if requested.
|
||||
*
|
||||
* This includes all display items created by this frame, including
|
||||
* container types.
|
||||
* @param aFlags INVALIDATE_DONT_SCHEDULE_PAINT: Don't call SchedulePaint()
|
||||
* when invalidating.
|
||||
*/
|
||||
enum {
|
||||
INVALIDATE_DONT_SCHEDULE_PAINT
|
||||
};
|
||||
virtual void InvalidateFrame(uint32_t aFlags = 0);
|
||||
|
||||
/**
|
||||
* Calls InvalidateFrame() on all frames descendant frames (including
|
||||
* this one).
|
||||
*
|
||||
* This function doesn't walk through placeholder frames to invalidate
|
||||
* the out-of-flow frames.
|
||||
*/
|
||||
void InvalidateFrameSubtree(uint32_t aFlags = 0);
|
||||
|
||||
/**
|
||||
* Checks if a frame has had InvalidateFrame() called on it since the
|
||||
* last paint.
|
||||
*/
|
||||
bool IsInvalid();
|
||||
|
||||
/**
|
||||
* Check if any frame within the frame subtree (including this frame)
|
||||
* returns true for IsInvalid().
|
||||
*/
|
||||
bool HasInvalidFrameInSubtree()
|
||||
{
|
||||
return HasAnyStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the invalid state from the current frame and all
|
||||
* descendant frames.
|
||||
*/
|
||||
void ClearInvalidationStateBits();
|
||||
|
||||
/**
|
||||
* Ensures that the refresh driver is running, and schedules a view
|
||||
* manager flush on the next tick.
|
||||
*
|
||||
* The view manager flush will update the layer tree, repaint any
|
||||
* invalid areas in the layer tree and schedule a layer tree
|
||||
* composite operation to display the layer tree.
|
||||
*/
|
||||
void SchedulePaint();
|
||||
|
||||
/**
|
||||
* Checks if the layer tree includes a dedicated layer for this
|
||||
* frame/display item key pair, and invalidates at least aDamageRect
|
||||
* area within that layer.
|
||||
*
|
||||
* If no layer is found, calls InvalidateFrame() instead.
|
||||
*
|
||||
* @param aDamageRect Area of the layer to invalidate.
|
||||
* @param aDisplayItemKey Display item type.
|
||||
* @return Layer, if found, nullptr otherwise.
|
||||
*/
|
||||
Layer* InvalidateLayer(const nsRect& aDamageRect, uint32_t aDisplayItemKey);
|
||||
|
||||
/**
|
||||
* Returns a rect that encompasses everything that might be painted by
|
||||
* this frame. This includes this frame, all its descendent frames, this
|
||||
|
@ -954,6 +954,9 @@ nsSubDocumentFrame::BeginSwapDocShells(nsIFrame* aOther)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_ASSERTION(HasAnyStateBits(NS_FRAME_IN_POPUP) == other->HasAnyStateBits(NS_FRAME_IN_POPUP),
|
||||
"Can't swap doc shells when only one is within a popup!");
|
||||
|
||||
if (mInnerView && other->mInnerView) {
|
||||
nsIView* ourSubdocViews = mInnerView->GetFirstChild();
|
||||
nsIView* ourRemovedViews = ::BeginSwapDocShellsForViews(ourSubdocViews);
|
||||
@ -1008,6 +1011,14 @@ EndSwapDocShellsForViews(nsIView* aSibling)
|
||||
if (doc) {
|
||||
::EndSwapDocShellsForDocument(doc, nullptr);
|
||||
}
|
||||
nsIFrame *frame = aSibling->GetFrame();
|
||||
if (frame && frame->HasInvalidFrameInSubtree()) {
|
||||
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(frame);
|
||||
while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
|
||||
parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,16 @@ ViewportFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
return Super::Init(aContent, aParent, aPrevInFlow);
|
||||
nsresult rv = Super::Init(aContent, aParent, aPrevInFlow);
|
||||
|
||||
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(this);
|
||||
if (parent) {
|
||||
nsFrameState state = parent->GetStateBits();
|
||||
|
||||
mState |= state & (NS_FRAME_IN_POPUP);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -170,6 +170,8 @@ nsMenuPopupFrame::Init(nsIContent* aContent,
|
||||
}
|
||||
}
|
||||
|
||||
AddStateBits(NS_FRAME_IN_POPUP);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user