зеркало из https://github.com/mozilla/gecko-dev.git
Bug 339889. Propagate invalidation through the frame hierarchy to topmost widgets. r+sr=bzbarsky
This commit is contained in:
Родитель
6ff46c21cf
Коммит
597d8bc582
|
@ -2151,6 +2151,16 @@ nsListControlFrame::GetType() const
|
|||
return nsLayoutAtoms::listControlFrame;
|
||||
}
|
||||
|
||||
void
|
||||
nsListControlFrame::InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate)
|
||||
{
|
||||
if (!IsInDropDownMode())
|
||||
return nsHTMLScrollFrame::InvalidateInternal(aDamageRect, aX, aY, aForChild, aImmediate);
|
||||
InvalidateRoot(aDamageRect, aX, aY, aImmediate);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsListControlFrame::GetFrameName(nsAString& aResult) const
|
||||
|
|
|
@ -119,6 +119,10 @@ public:
|
|||
*/
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate);
|
||||
|
||||
#ifdef DEBUG
|
||||
// nsIFrameDebug
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
|
|
|
@ -480,6 +480,28 @@ nsBlockFrame::GetType() const
|
|||
return nsLayoutAtoms::blockFrame;
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockFrame::InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate)
|
||||
{
|
||||
// Optimize by suppressing invalidation of areas that are clipped out
|
||||
// with CSS 'clip'.
|
||||
const nsStyleDisplay* disp = GetStyleDisplay();
|
||||
nsRect absPosClipRect;
|
||||
if (GetAbsPosClipRect(disp, &absPosClipRect)) {
|
||||
// Restrict the invalidated area to abs-pos clip rect
|
||||
// abs-pos clipping clips everything in the frame
|
||||
nsRect r;
|
||||
if (r.IntersectRect(aDamageRect, absPosClipRect - nsPoint(aX, aY))) {
|
||||
nsBlockFrameSuper::InvalidateInternal(r, aX, aY, aForChild, aImmediate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsBlockFrameSuper::InvalidateInternal(aDamageRect, aX, aY, aForChild, aImmediate);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Child frame enumeration
|
||||
|
||||
|
|
|
@ -165,6 +165,9 @@ public:
|
|||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate);
|
||||
virtual nsIAtom* GetType() const;
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
|
||||
|
|
|
@ -954,12 +954,36 @@ nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
|
|||
return DisplayOutlineUnconditional(aBuilder, aLists);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsIFrame::GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect)
|
||||
{
|
||||
NS_PRECONDITION(aRect, "Must have aRect out parameter");
|
||||
|
||||
if (!aDisp->IsAbsolutelyPositioned() ||
|
||||
!(aDisp->mClipFlags & NS_STYLE_CLIP_RECT))
|
||||
return PR_FALSE;
|
||||
|
||||
// Start with the 'auto' values and then factor in user specified values
|
||||
aRect->SetRect(nsPoint(0, 0), GetSize());
|
||||
if (0 == (NS_STYLE_CLIP_TOP_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->y += aDisp->mClip.y;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_LEFT_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->x += aDisp->mClip.x;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->width = aDisp->mClip.width;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->height = aDisp->mClip.height;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
|
||||
const nsStyleDisplay* aDisp, nsIFrame* aFrame,
|
||||
nsRect* aRect) {
|
||||
// REVIEW: from nsContainerFrame.cpp SyncFrameViewGeometryDependentProperties
|
||||
if (!aDisp->IsAbsolutelyPositioned() ||
|
||||
!(aDisp->mClipFlags & NS_STYLE_CLIP_RECT))
|
||||
if (!aFrame->GetAbsPosClipRect(aDisp, aRect))
|
||||
return PR_FALSE;
|
||||
|
||||
// A moving frame should not be allowed to clip a non-moving frame.
|
||||
|
@ -976,21 +1000,7 @@ static PRBool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
|
|||
GetFirstChild(nsLayoutAtoms::fixedList) &&
|
||||
aBuilder->IsMovingFrame(aFrame))
|
||||
return PR_FALSE;
|
||||
|
||||
// Start with the 'auto' values and then factor in user specified values
|
||||
aRect->SetRect(aBuilder->ToReferenceFrame(aFrame), aFrame->GetSize());
|
||||
if (0 == (NS_STYLE_CLIP_TOP_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->y += aDisp->mClip.y;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_LEFT_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->x += aDisp->mClip.x;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->width = aDisp->mClip.width;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & aDisp->mClipFlags)) {
|
||||
aRect->height = aDisp->mClip.height;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -3127,7 +3137,7 @@ nsIFrame::IsLeaf() const
|
|||
|
||||
void
|
||||
nsIFrame::Invalidate(const nsRect& aDamageRect,
|
||||
PRBool aImmediate) const
|
||||
PRBool aImmediate)
|
||||
{
|
||||
if (aDamageRect.IsEmpty()) {
|
||||
return;
|
||||
|
@ -3142,23 +3152,26 @@ nsIFrame::Invalidate(const nsRect& aDamageRect,
|
|||
if (suppressed)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRect damageRect(aDamageRect);
|
||||
|
||||
PRUint32 flags = aImmediate ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
|
||||
if (HasView()) {
|
||||
nsIView* view = GetView();
|
||||
view->GetViewManager()->UpdateView(view, damageRect, flags);
|
||||
} else {
|
||||
nsRect rect(damageRect);
|
||||
nsPoint offset;
|
||||
|
||||
nsIView *view;
|
||||
GetOffsetFromView(offset, &view);
|
||||
NS_ASSERTION(view, "no view");
|
||||
rect += offset;
|
||||
view->GetViewManager()->UpdateView(view, rect, flags);
|
||||
}
|
||||
InvalidateInternal(aDamageRect, 0, 0, nsnull, aImmediate);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
|
||||
nsIFrame* aForChild, PRBool aImmediate)
|
||||
{
|
||||
GetParent()->
|
||||
InvalidateInternal(aDamageRect, aX + mRect.x, aY + mRect.y, this, aImmediate);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateRoot(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, PRBool aImmediate)
|
||||
{
|
||||
PRUint32 flags = aImmediate ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
|
||||
nsIView* view = GetView();
|
||||
NS_ASSERTION(view, "This can only be called on frames with views");
|
||||
view->GetViewManager()->UpdateView(view, aDamageRect + nsPoint(aX, aY), flags);
|
||||
}
|
||||
|
||||
static nsRect ComputeOutlineRect(const nsIFrame* aFrame, PRBool* aAnyOutline,
|
||||
|
|
|
@ -1379,6 +1379,27 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGfxScrollFrameInner::InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate)
|
||||
{
|
||||
nsPoint pt = mOuter->GetPosition();
|
||||
|
||||
if (aForChild == mScrolledFrame) {
|
||||
// restrict aDamageRect to the scrollable view's bounds
|
||||
nsRect r;
|
||||
if (r.IntersectRect(aDamageRect, mScrollableView->View()->GetBounds() - nsPoint(aX, aY))) {
|
||||
mOuter->GetParent()->
|
||||
InvalidateInternal(r, aX + pt.x, aY + pt.y, mOuter, aImmediate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mOuter->GetParent()->
|
||||
InvalidateInternal(aDamageRect, aX + pt.x, aY + pt.y, mOuter, aImmediate);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGfxScrollFrameInner::NeedsClipWidget() const
|
||||
{
|
||||
|
|
|
@ -88,6 +88,9 @@ public:
|
|||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
|
||||
nsIFrame* aForChild, PRBool aImmediate);
|
||||
|
||||
// nsIScrollPositionListener
|
||||
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
|
@ -266,6 +269,12 @@ public:
|
|||
return mInner.GetScrolledFrame()->GetView();
|
||||
}
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate) {
|
||||
return mInner.InvalidateInternal(aDamageRect, aX, aY, aForChild, aImmediate);
|
||||
}
|
||||
|
||||
virtual PRBool NeedsView() { return PR_TRUE; }
|
||||
virtual PRBool DoesClipChildren() { return PR_TRUE; }
|
||||
|
||||
|
@ -401,6 +410,12 @@ public:
|
|||
return mInner.GetScrolledFrame()->GetView();
|
||||
}
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate) {
|
||||
return mInner.InvalidateInternal(aDamageRect, aX, aY, aForChild, aImmediate);
|
||||
}
|
||||
|
||||
virtual PRBool NeedsView() { return PR_TRUE; }
|
||||
virtual PRBool DoesClipChildren() { return PR_TRUE; }
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
* http://www.mozilla.org/MPL/I
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
|
@ -1212,14 +1212,33 @@ public:
|
|||
/**
|
||||
* Invalidate part of the frame by asking the view manager to repaint.
|
||||
* aDamageRect is allowed to extend outside the frame's bounds. We'll do the right
|
||||
* thing. But it must be within the bounds of the view enclosing this frame.
|
||||
* thing.
|
||||
* We deliberately don't have an Invalidate() method that defaults to the frame's bounds.
|
||||
* We want all callers to *think* about what has changed in the frame and what area might
|
||||
* need to be repainted.
|
||||
*
|
||||
* @param aDamageRect is in the frame's local coordinate space
|
||||
*/
|
||||
void Invalidate(const nsRect& aDamageRect, PRBool aImmediate = PR_FALSE) const;
|
||||
void Invalidate(const nsRect& aDamageRect, PRBool aImmediate = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Helper function that can be overridden by frame classes. The rectangle
|
||||
* (plus aOffsetX/aOffsetY) is relative to this frame.
|
||||
*
|
||||
* The offset is given as two coords rather than as an nsPoint because
|
||||
* gcc optimizes it better that way, in particular in the default
|
||||
* implementation that passes the area to the parent frame becomes a tail
|
||||
* call.
|
||||
*
|
||||
* The default implementation will crash if the frame has no parent so
|
||||
* frames without parents MUST* override.
|
||||
*
|
||||
* @param aForChild if the invalidation is coming from a child frame, this
|
||||
* is the frame; otherwise, this is null.
|
||||
*/
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aOffsetX, nscoord aOffsetY,
|
||||
nsIFrame* aForChild, PRBool aImmediate);
|
||||
|
||||
/**
|
||||
* Computes a rect that includes this frame, all its descendant
|
||||
|
@ -1477,6 +1496,14 @@ NS_PTR_TO_INT32(frame->GetProperty(nsLayoutAtoms::embeddingLevel))
|
|||
*/
|
||||
virtual PRBool SupportsVisibilityHidden() { return PR_TRUE; }
|
||||
|
||||
/**
|
||||
* Returns PR_TRUE if the frame is absolutely positioned and has a clip
|
||||
* rect set via the 'clip' property. If true, then we also set aRect
|
||||
* to the computed clip rect coordinates relative to this frame's origin.
|
||||
* aRect must not be null!
|
||||
*/
|
||||
PRBool GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect);
|
||||
|
||||
/**
|
||||
* Check if this frame is focusable and in the current tab order.
|
||||
* Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
|
||||
|
@ -1640,6 +1667,15 @@ protected:
|
|||
nsIFrame* mParent;
|
||||
nsIFrame* mNextSibling; // singly-linked list of frames
|
||||
nsFrameState mState;
|
||||
|
||||
// Helpers
|
||||
/**
|
||||
* For frames that have top-level windows (top-level viewports,
|
||||
* comboboxes, menupoups) this function will invalidate the window.
|
||||
*/
|
||||
void InvalidateRoot(const nsRect& aDamageRect,
|
||||
nscoord aOffsetX, nscoord aOffsetY,
|
||||
PRBool aImmediate);
|
||||
|
||||
private:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
|
||||
|
|
|
@ -333,6 +333,20 @@ ViewportFrame::IsContainingBlock() const
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ViewportFrame::InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate)
|
||||
{
|
||||
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(this);
|
||||
if (parent) {
|
||||
nsPoint pt = GetOffsetTo(parent);
|
||||
parent->InvalidateInternal(aDamageRect, aX + pt.x, aY + pt.y, this, aImmediate);
|
||||
return;
|
||||
}
|
||||
InvalidateRoot(aDamageRect, aX, aY, aImmediate);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
ViewportFrame::GetFrameName(nsAString& aResult) const
|
||||
|
|
|
@ -107,6 +107,10 @@ public:
|
|||
|
||||
virtual PRBool IsContainingBlock() const;
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate);
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
#endif
|
||||
|
|
|
@ -242,6 +242,14 @@ nsMenuPopupFrame::CreateWidgetForView(nsIView* aView)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuPopupFrame::InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate)
|
||||
{
|
||||
InvalidateRoot(aDamageRect, aX, aY, aImmediate);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuPopupFrame::MarkStyleChange(nsBoxLayoutState& aState)
|
||||
{
|
||||
|
|
|
@ -154,6 +154,10 @@ public:
|
|||
|
||||
virtual void Destroy();
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate);
|
||||
|
||||
virtual nsresult CreateWidgetForView(nsIView* aView);
|
||||
|
||||
NS_IMETHOD MarkStyleChange(nsBoxLayoutState& aState);
|
||||
|
|
Загрузка…
Ссылка в новой задаче