зеркало из https://github.com/mozilla/gecko-dev.git
Invalidate the canvas correctly when <body> and root nodes are added to or
removed from documents. Bug 321751, r+sr=roc
This commit is contained in:
Родитель
922ae3e21a
Коммит
71e963c9c7
|
@ -8657,6 +8657,9 @@ GetAdjustedParentFrame(nsIFrame* aParentFrame,
|
|||
return (newParent) ? newParent : aParentFrame;
|
||||
}
|
||||
|
||||
static void
|
||||
InvalidateCanvasIfNeeded(nsIFrame* aFrame);
|
||||
|
||||
nsresult
|
||||
nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
|
@ -8894,9 +8897,13 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
// the outer table frame's additional child list.
|
||||
nsFrameItems captionItems;
|
||||
|
||||
// The last frame that we added to the list.
|
||||
nsIFrame* oldNewFrame = nsnull;
|
||||
|
||||
PRUint32 i;
|
||||
count = aContainer->GetChildCount();
|
||||
for (i = aNewIndexInContainer; i < count; i++) {
|
||||
nsIFrame* newFrame = nsnull;
|
||||
nsIContent *childContent = aContainer->GetChildAt(i);
|
||||
// lookup the table child frame type as it is much more difficult to remove a frame
|
||||
// and all it descendants (abs. pos. for instance) than to prevent the frame creation.
|
||||
|
@ -8910,6 +8917,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
else {
|
||||
frameItems.AddChild(tempItems.childList);
|
||||
}
|
||||
newFrame = tempItems.childList;
|
||||
}
|
||||
}
|
||||
else if (nsLayoutAtoms::tableColGroupFrame == frameType) {
|
||||
|
@ -8918,12 +8926,17 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
|
|||
if (childStyleContext->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_TABLE_COLUMN)
|
||||
continue; //don't create anything else than columns below a colgroup
|
||||
ConstructFrame(state, childContent, parentFrame, frameItems);
|
||||
newFrame = frameItems.lastChild;
|
||||
}
|
||||
// Don't create child frames for iframes/frames, they should not
|
||||
// display any content that they contain.
|
||||
else if (nsLayoutAtoms::subDocumentFrame != frameType) {
|
||||
else {
|
||||
// Construct a child frame (that does not have a table as parent)
|
||||
ConstructFrame(state, childContent, parentFrame, frameItems);
|
||||
newFrame = frameItems.lastChild;
|
||||
}
|
||||
|
||||
if (newFrame && newFrame != oldNewFrame) {
|
||||
InvalidateCanvasIfNeeded(newFrame);
|
||||
oldNewFrame = newFrame;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9242,6 +9255,10 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer,
|
|||
mDocElementContainingBlock->AppendFrames(nsnull, docElementFrame);
|
||||
}
|
||||
|
||||
if (docElementFrame) {
|
||||
InvalidateCanvasIfNeeded(docElementFrame);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (gReallyNoisyContentUpdates && docElementFrame) {
|
||||
nsIFrameDebug* fdbg = nsnull;
|
||||
|
@ -9461,6 +9478,8 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer,
|
|||
|
||||
ConstructFrame(state, aChild, parentFrame, tempItems);
|
||||
if (tempItems.childList) {
|
||||
InvalidateCanvasIfNeeded(tempItems.childList);
|
||||
|
||||
if (nsLayoutAtoms::tableCaptionFrame == tempItems.childList->GetType()) {
|
||||
captionItems.AddChild(tempItems.childList);
|
||||
}
|
||||
|
@ -9571,6 +9590,9 @@ nsCSSFrameConstructor::ReinsertContent(nsIContent* aContainer,
|
|||
{
|
||||
PRInt32 ix = aContainer->IndexOf(aChild);
|
||||
// XXX For now, do a brute force remove and insert.
|
||||
// XXXbz this probably doesn't work so well with anonymous content
|
||||
// XXXbz doesn't this need to do the state-saving stuff that
|
||||
// RecreateFramesForContent does?
|
||||
nsresult res = ContentRemoved(aContainer, aChild, ix, PR_TRUE);
|
||||
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
|
@ -9807,6 +9829,8 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
|
|||
#endif // MOZ_XUL
|
||||
|
||||
if (childFrame) {
|
||||
InvalidateCanvasIfNeeded(childFrame);
|
||||
|
||||
// If the frame we are manipulating is a special frame then do
|
||||
// something different instead of just inserting newly created
|
||||
// frames.
|
||||
|
@ -9999,8 +10023,7 @@ static PRBool gInApplyRenderingChangeToTree = PR_FALSE;
|
|||
#endif
|
||||
|
||||
static void
|
||||
DoApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
||||
nsIViewManager* aViewManager,
|
||||
nsFrameManager* aFrameManager,
|
||||
nsChangeHint aChange);
|
||||
|
@ -10010,8 +10033,8 @@ DoApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
|||
* This rect is relative to aFrame's parent
|
||||
*/
|
||||
static void
|
||||
UpdateViewsForTree(nsPresContext* aPresContext, nsIFrame* aFrame,
|
||||
nsIViewManager* aViewManager, nsFrameManager* aFrameManager,
|
||||
UpdateViewsForTree(nsIFrame* aFrame, nsIViewManager* aViewManager,
|
||||
nsFrameManager* aFrameManager,
|
||||
nsRect& aBoundsRect, nsChangeHint aChange)
|
||||
{
|
||||
NS_PRECONDITION(gInApplyRenderingChangeToTree,
|
||||
|
@ -10023,7 +10046,8 @@ UpdateViewsForTree(nsPresContext* aPresContext, nsIFrame* aFrame,
|
|||
aViewManager->UpdateView(view, NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
if (aChange & nsChangeHint_SyncFrameView) {
|
||||
nsContainerFrame::SyncFrameViewProperties(aPresContext, aFrame, nsnull, view);
|
||||
nsContainerFrame::SyncFrameViewProperties(aFrame->GetPresContext(),
|
||||
aFrame, nsnull, view);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10044,12 +10068,13 @@ UpdateViewsForTree(nsPresContext* aPresContext, nsIFrame* aFrame,
|
|||
nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
|
||||
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
||||
|
||||
DoApplyRenderingChangeToTree(aPresContext, outOfFlowFrame,
|
||||
aViewManager, aFrameManager, aChange);
|
||||
DoApplyRenderingChangeToTree(outOfFlowFrame, aViewManager,
|
||||
aFrameManager, aChange);
|
||||
}
|
||||
else { // regular frame
|
||||
nsRect childBounds;
|
||||
UpdateViewsForTree(aPresContext, child, aViewManager, aFrameManager, childBounds, aChange);
|
||||
UpdateViewsForTree(child, aViewManager, aFrameManager, childBounds,
|
||||
aChange);
|
||||
bounds.UnionRect(bounds, childBounds);
|
||||
}
|
||||
}
|
||||
|
@ -10063,8 +10088,7 @@ UpdateViewsForTree(nsPresContext* aPresContext, nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
static void
|
||||
DoApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
||||
nsIViewManager* aViewManager,
|
||||
nsFrameManager* aFrameManager,
|
||||
nsChangeHint aChange)
|
||||
|
@ -10078,8 +10102,8 @@ DoApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
|||
// (adjusting r's coordinate system to reflect the nesting) and
|
||||
// update there.
|
||||
nsRect invalidRect;
|
||||
UpdateViewsForTree(aPresContext, aFrame, aViewManager, aFrameManager,
|
||||
invalidRect, aChange);
|
||||
UpdateViewsForTree(aFrame, aViewManager, aFrameManager, invalidRect,
|
||||
aChange);
|
||||
|
||||
if (!aFrame->HasView()
|
||||
&& (aChange & nsChangeHint_RepaintFrame)) {
|
||||
|
@ -10094,7 +10118,6 @@ DoApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
|||
static void
|
||||
ApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsIViewManager* aViewManager,
|
||||
nsChangeHint aChange)
|
||||
{
|
||||
nsIPresShell *shell = aPresContext->PresShell();
|
||||
|
@ -10118,10 +10141,7 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
|||
NS_ASSERTION(aFrame, "root frame must paint");
|
||||
}
|
||||
|
||||
nsIViewManager* viewManager = aViewManager;
|
||||
if (!viewManager) {
|
||||
viewManager = aPresContext->GetViewManager();
|
||||
}
|
||||
nsIViewManager* viewManager = aPresContext->GetViewManager();
|
||||
|
||||
// Trigger rendering updates by damaging this frame and any
|
||||
// continuations of this frame.
|
||||
|
@ -10133,8 +10153,8 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
|||
#ifdef DEBUG
|
||||
gInApplyRenderingChangeToTree = PR_TRUE;
|
||||
#endif
|
||||
DoApplyRenderingChangeToTree(aPresContext, aFrame, viewManager,
|
||||
shell->FrameManager(), aChange);
|
||||
DoApplyRenderingChangeToTree(aFrame, viewManager, shell->FrameManager(),
|
||||
aChange);
|
||||
#ifdef DEBUG
|
||||
gInApplyRenderingChangeToTree = PR_FALSE;
|
||||
#endif
|
||||
|
@ -10142,6 +10162,59 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext,
|
|||
viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method invalidates the canvas when frames are removed or added for a
|
||||
* node that might have its background propagated to the canvas, i.e., a
|
||||
* document root node or an HTML BODY which is a child of the root node.
|
||||
*
|
||||
* @param aFrame a frame for a content node about to be removed or a frme that
|
||||
* was just created for a content node that was inserted.
|
||||
*/
|
||||
static void
|
||||
InvalidateCanvasIfNeeded(nsIFrame* aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "Must have frame!");
|
||||
|
||||
// Note that for both in ContentRemoved and ContentInserted the content node
|
||||
// will still have the right parent pointer, so looking at that is ok.
|
||||
|
||||
nsIContent* node = aFrame->GetContent();
|
||||
nsIContent* parent = node->GetParent();
|
||||
if (parent) {
|
||||
// Has a parent; might not be what we want
|
||||
nsIContent* grandParent = parent->GetParent();
|
||||
if (grandParent) {
|
||||
// Has a grandparent, so not what we want
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether it's an HTML body
|
||||
if (node->Tag() != nsHTMLAtoms::body ||
|
||||
!node->IsContentOfType(nsIContent::eHTML)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point the node has no parent or it's an HTML <body> child of the
|
||||
// root. We might not need to invalidate in this case (eg we might be in
|
||||
// XHTML or something), but chances are we want to. Play it safe. Find the
|
||||
// frame to invalidate and do it.
|
||||
nsIFrame *ancestor = aFrame;
|
||||
const nsStyleBackground *bg;
|
||||
PRBool isCanvas;
|
||||
nsPresContext* presContext = aFrame->GetPresContext();
|
||||
while (!nsCSSRendering::FindBackground(presContext, ancestor,
|
||||
&bg, &isCanvas)) {
|
||||
ancestor = ancestor->GetParent();
|
||||
NS_ASSERTION(ancestor, "canvas must paint");
|
||||
}
|
||||
|
||||
if (ancestor != aFrame) {
|
||||
ApplyRenderingChangeToTree(presContext, ancestor,
|
||||
nsChangeHint_RepaintFrame);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSFrameConstructor::StyleChangeReflow(nsIFrame* aFrame,
|
||||
nsIAtom* aAttribute)
|
||||
|
@ -10332,8 +10405,7 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
|||
StyleChangeReflow(frame, nsnull);
|
||||
}
|
||||
if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView)) {
|
||||
ApplyRenderingChangeToTree(mPresShell->GetPresContext(), frame, nsnull,
|
||||
hint);
|
||||
ApplyRenderingChangeToTree(mPresShell->GetPresContext(), frame, hint);
|
||||
}
|
||||
if (hint & nsChangeHint_UpdateCursor) {
|
||||
nsIViewManager* viewMgr = mPresShell->GetViewManager();
|
||||
|
@ -11438,27 +11510,10 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent)
|
|||
// below!)
|
||||
|
||||
nsIFrame* frame = mPresShell->GetPrimaryFrameFor(aContent);
|
||||
nsPresContext* presContext = mPresShell->GetPresContext();
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (frame) {
|
||||
// If the background of the frame is painted on one of its ancestors,
|
||||
// the frame reconstruct might not invalidate correctly.
|
||||
nsIFrame *ancestor = frame;
|
||||
const nsStyleBackground *bg;
|
||||
PRBool isCanvas;
|
||||
while (!nsCSSRendering::FindBackground(presContext, ancestor,
|
||||
&bg, &isCanvas)) {
|
||||
ancestor = ancestor->GetParent();
|
||||
NS_ASSERTION(ancestor, "canvas must paint");
|
||||
}
|
||||
// This isn't the most efficient way to do it, but it saves code
|
||||
// size and doesn't add much cost compared to the frame reconstruct.
|
||||
if (ancestor != frame)
|
||||
ApplyRenderingChangeToTree(presContext, ancestor, nsnull,
|
||||
nsChangeHint_RepaintFrame);
|
||||
|
||||
// If the frame is an anonymous frame created as part of inline-in-block
|
||||
// splitting --- or if its parent is such an anonymous frame (i.e., this
|
||||
// frame might have been the cause of such splitting), then recreate the
|
||||
|
@ -11473,6 +11528,7 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent)
|
|||
|
||||
nsCOMPtr<nsIContent> container = aContent->GetParent();
|
||||
if (container) {
|
||||
// XXXbz what if this is anonymous content?
|
||||
PRInt32 indexInContainer = container->IndexOf(aContent);
|
||||
// Before removing the frames associated with the content object,
|
||||
// ask them to save their state onto a temporary state object.
|
||||
|
|
Загрузка…
Ссылка в новой задаче