Make iframe border repaint when style changes (bug 124507), r=waterson@netscape.com, sr=attinasi@netscape.com

This commit is contained in:
jkeiser%netscape.com 2002-04-28 07:53:41 +00:00
parent 4461167d71
commit 900ba63a0b
8 changed files with 268 additions and 176 deletions

View File

@ -783,7 +783,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
nsresult rv = NS_OK;
PRBool isStyleChange = PR_FALSE;
nsIFrame* target;
switch (aReflowState.reason) {
@ -813,7 +812,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
switch (type) {
case eReflowType_StyleChanged:
rv = PrepareStyleChangedReflow(state);
isStyleChange = PR_TRUE;
break;
case eReflowType_ReflowDirty:
// Do nothing; the dirty lines will already have been marked.
@ -908,87 +906,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
#endif
// If this is an incremental reflow and we changed size, then make sure our
// border is repainted if necessary
if ((eReflowReason_Incremental == aReflowState.reason ||
eReflowReason_Dirty == aReflowState.reason)) {
if (isStyleChange) {
// This is only true if it's a style change reflow targeted at this
// frame (rather than an ancestor) (I think). That seems to be
// what's wanted here.
// Lots of things could have changed so damage our entire
// bounds
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
this, 0, 0, mRect.width, mRect.height);
#endif
nsRect damageRect(0, 0, mRect.width, mRect.height);
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext,damageRect);
}
} else {
nsMargin border = aReflowState.mComputedBorderPadding -
aReflowState.mComputedPadding;
// See if our width changed
if ((aMetrics.width != mRect.width) && (border.right > 0)) {
nsRect damageRect;
if (aMetrics.width < mRect.width) {
// Our new width is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = aMetrics.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = aMetrics.height;
} else {
// Our new width is larger, so we need to erase our border in its
// old position
damageRect.x = mRect.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = mRect.height;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
// See if our height changed
if ((aMetrics.height != mRect.height) && (border.bottom > 0)) {
nsRect damageRect;
if (aMetrics.height < mRect.height) {
// Our new height is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = 0;
damageRect.width = aMetrics.width;
damageRect.y = aMetrics.height - border.bottom;
damageRect.height = border.bottom;
} else {
// Our new height is larger, so we need to erase our border in its
// old position
damageRect.x = 0;
damageRect.width = mRect.width;
damageRect.y = mRect.height - border.bottom;
damageRect.height = border.bottom;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
}
}
// Determine if we need to repaint our border
CheckInvalidateBorder(aPresContext, aMetrics, aReflowState);
// Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed, e.g., elements with a percentage

View File

@ -550,9 +550,22 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext* aPresContext,
}
// Place and size the child
FinishReflowChild(firstChild, aPresContext, nsnull,
FinishReflowChild(firstChild, aPresContext, nsnull,
kidMetrics, offset.x, offset.y, 0);
// Determine if we need to repaint our border
CheckInvalidateBorder(aPresContext, aDesiredSize, aReflowState);
{
// Invalidate the frame
nsRect frameRect;
GetRect(frameRect);
nsRect rect(0, 0, frameRect.width, frameRect.height);
if (!rect.IsEmpty()) {
Invalidate(aPresContext, rect, PR_FALSE);
}
}
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("exit nsHTMLFrameOuterFrame::Reflow: size=%d,%d status=%x",
aDesiredSize.width, aDesiredSize.height, aStatus));
@ -876,9 +889,9 @@ nsHTMLFrameInnerFrame::Paint(nsIPresContext* aPresContext,
PRUint32 aFlags)
{
//printf("inner paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x,
//aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); if there is
//not web shell paint based on our background color, otherwise let
//the web shell paint the sub document
//aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
// if there is not web shell paint based on our background color, otherwise
// let the web shell paint the sub document
// isPaginated is a temporary fix for Bug 75737 and this should all
// be fixed correctly by Bug 75739

View File

@ -682,3 +682,103 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext,
}
return NS_OK;
}
void
nsHTMLContainerFrame::CheckInvalidateBorder(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState)
{
// XXX This method ought to deal with padding as well
// If this is a style change reflow targeted at this frame, we must repaint
// everything (well, we really just have to repaint the borders but we're
// a bunch of lazybones).
if (aReflowState.reason == eReflowReason_Incremental) {
nsIFrame* target;
aReflowState.reflowCommand->GetTarget(target);
if (target == this) {
nsReflowType type;
aReflowState.reflowCommand->GetType(type);
if (type == eReflowType_StyleChanged) {
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
this, 0, 0, mRect.width, mRect.height);
#endif
// Lots of things could have changed so damage our entire bounds
nsRect damageRect(0, 0, mRect.width, mRect.height);
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext,damageRect);
}
return;
}
}
}
// If we changed size, we must invalidate the parts of us that have changed
// to make the border show up.
if ((aReflowState.reason == eReflowReason_Incremental ||
aReflowState.reason == eReflowReason_Dirty)) {
nsMargin border = aReflowState.mComputedBorderPadding -
aReflowState.mComputedPadding;
// See if our width changed
if ((aDesiredSize.width != mRect.width) && (border.right > 0)) {
nsRect damageRect;
if (aDesiredSize.width < mRect.width) {
// Our new width is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = aDesiredSize.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = aDesiredSize.height;
} else {
// Our new width is larger, so we need to erase our border in its
// old position
damageRect.x = mRect.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = mRect.height;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
// See if our height changed
if ((aDesiredSize.height != mRect.height) && (border.bottom > 0)) {
nsRect damageRect;
if (aDesiredSize.height < mRect.height) {
// Our new height is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = 0;
damageRect.width = aDesiredSize.width;
damageRect.y = aDesiredSize.height - border.bottom;
damageRect.height = border.bottom;
} else {
// Our new height is larger, so we need to erase our border in its
// old position
damageRect.x = 0;
damageRect.width = mRect.width;
damageRect.y = mRect.height - border.bottom;
damageRect.height = border.bottom;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
}
}

View File

@ -43,6 +43,8 @@ class nsAbsoluteFrame;
class nsPlaceholderFrame;
struct nsStyleDisplay;
struct nsStylePosition;
struct nsHTMLReflowMetrics;
struct nsHTMLReflowState;
// Some macros for container classes to do sanity checking on
// width/height/x/y values computed during reflow.
@ -98,12 +100,24 @@ public:
nsIFrame* aChildFrame,
nsIFrame* aOldParentFrame,
nsIFrame* aNewParentFrame);
static nsresult ReparentFrameViewList(nsIPresContext* aPresContext,
nsIFrame* aChildFrameList,
nsIFrame* aOldParentFrame,
nsIFrame* aNewParentFrame);
/**
* Helper method to invalidate portions of a standard container frame if the
* reflow state indicates that they have changed (specifically border and
* padding).
* @param aPresContext the presentation context
* @param aDesiredSize the new size of the frame
* @param aReflowState the reflow that was just done on this frame
*/
void CheckInvalidateBorder(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState);
protected:
virtual PRIntn GetSkipSides() const = 0;
};

View File

@ -783,7 +783,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
nsresult rv = NS_OK;
PRBool isStyleChange = PR_FALSE;
nsIFrame* target;
switch (aReflowState.reason) {
@ -813,7 +812,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
switch (type) {
case eReflowType_StyleChanged:
rv = PrepareStyleChangedReflow(state);
isStyleChange = PR_TRUE;
break;
case eReflowType_ReflowDirty:
// Do nothing; the dirty lines will already have been marked.
@ -908,87 +906,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
#endif
// If this is an incremental reflow and we changed size, then make sure our
// border is repainted if necessary
if ((eReflowReason_Incremental == aReflowState.reason ||
eReflowReason_Dirty == aReflowState.reason)) {
if (isStyleChange) {
// This is only true if it's a style change reflow targeted at this
// frame (rather than an ancestor) (I think). That seems to be
// what's wanted here.
// Lots of things could have changed so damage our entire
// bounds
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
this, 0, 0, mRect.width, mRect.height);
#endif
nsRect damageRect(0, 0, mRect.width, mRect.height);
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext,damageRect);
}
} else {
nsMargin border = aReflowState.mComputedBorderPadding -
aReflowState.mComputedPadding;
// See if our width changed
if ((aMetrics.width != mRect.width) && (border.right > 0)) {
nsRect damageRect;
if (aMetrics.width < mRect.width) {
// Our new width is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = aMetrics.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = aMetrics.height;
} else {
// Our new width is larger, so we need to erase our border in its
// old position
damageRect.x = mRect.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = mRect.height;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
// See if our height changed
if ((aMetrics.height != mRect.height) && (border.bottom > 0)) {
nsRect damageRect;
if (aMetrics.height < mRect.height) {
// Our new height is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = 0;
damageRect.width = aMetrics.width;
damageRect.y = aMetrics.height - border.bottom;
damageRect.height = border.bottom;
} else {
// Our new height is larger, so we need to erase our border in its
// old position
damageRect.x = 0;
damageRect.width = mRect.width;
damageRect.y = mRect.height - border.bottom;
damageRect.height = border.bottom;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
}
}
// Determine if we need to repaint our border
CheckInvalidateBorder(aPresContext, aMetrics, aReflowState);
// Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed, e.g., elements with a percentage

View File

@ -682,3 +682,103 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext,
}
return NS_OK;
}
void
nsHTMLContainerFrame::CheckInvalidateBorder(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState)
{
// XXX This method ought to deal with padding as well
// If this is a style change reflow targeted at this frame, we must repaint
// everything (well, we really just have to repaint the borders but we're
// a bunch of lazybones).
if (aReflowState.reason == eReflowReason_Incremental) {
nsIFrame* target;
aReflowState.reflowCommand->GetTarget(target);
if (target == this) {
nsReflowType type;
aReflowState.reflowCommand->GetType(type);
if (type == eReflowType_StyleChanged) {
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
this, 0, 0, mRect.width, mRect.height);
#endif
// Lots of things could have changed so damage our entire bounds
nsRect damageRect(0, 0, mRect.width, mRect.height);
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext,damageRect);
}
return;
}
}
}
// If we changed size, we must invalidate the parts of us that have changed
// to make the border show up.
if ((aReflowState.reason == eReflowReason_Incremental ||
aReflowState.reason == eReflowReason_Dirty)) {
nsMargin border = aReflowState.mComputedBorderPadding -
aReflowState.mComputedPadding;
// See if our width changed
if ((aDesiredSize.width != mRect.width) && (border.right > 0)) {
nsRect damageRect;
if (aDesiredSize.width < mRect.width) {
// Our new width is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = aDesiredSize.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = aDesiredSize.height;
} else {
// Our new width is larger, so we need to erase our border in its
// old position
damageRect.x = mRect.width - border.right;
damageRect.width = border.right;
damageRect.y = 0;
damageRect.height = mRect.height;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
// See if our height changed
if ((aDesiredSize.height != mRect.height) && (border.bottom > 0)) {
nsRect damageRect;
if (aDesiredSize.height < mRect.height) {
// Our new height is smaller, so we need to make sure that
// we paint our border in its new position
damageRect.x = 0;
damageRect.width = aDesiredSize.width;
damageRect.y = aDesiredSize.height - border.bottom;
damageRect.height = border.bottom;
} else {
// Our new height is larger, so we need to erase our border in its
// old position
damageRect.x = 0;
damageRect.width = mRect.width;
damageRect.y = mRect.height - border.bottom;
damageRect.height = border.bottom;
}
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
#endif
if (!damageRect.IsEmpty()) {
Invalidate(aPresContext, damageRect);
}
}
}
}

View File

@ -43,6 +43,8 @@ class nsAbsoluteFrame;
class nsPlaceholderFrame;
struct nsStyleDisplay;
struct nsStylePosition;
struct nsHTMLReflowMetrics;
struct nsHTMLReflowState;
// Some macros for container classes to do sanity checking on
// width/height/x/y values computed during reflow.
@ -98,12 +100,24 @@ public:
nsIFrame* aChildFrame,
nsIFrame* aOldParentFrame,
nsIFrame* aNewParentFrame);
static nsresult ReparentFrameViewList(nsIPresContext* aPresContext,
nsIFrame* aChildFrameList,
nsIFrame* aOldParentFrame,
nsIFrame* aNewParentFrame);
/**
* Helper method to invalidate portions of a standard container frame if the
* reflow state indicates that they have changed (specifically border and
* padding).
* @param aPresContext the presentation context
* @param aDesiredSize the new size of the frame
* @param aReflowState the reflow that was just done on this frame
*/
void CheckInvalidateBorder(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState);
protected:
virtual PRIntn GetSkipSides() const = 0;
};

View File

@ -550,9 +550,22 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext* aPresContext,
}
// Place and size the child
FinishReflowChild(firstChild, aPresContext, nsnull,
FinishReflowChild(firstChild, aPresContext, nsnull,
kidMetrics, offset.x, offset.y, 0);
// Determine if we need to repaint our border
CheckInvalidateBorder(aPresContext, aDesiredSize, aReflowState);
{
// Invalidate the frame
nsRect frameRect;
GetRect(frameRect);
nsRect rect(0, 0, frameRect.width, frameRect.height);
if (!rect.IsEmpty()) {
Invalidate(aPresContext, rect, PR_FALSE);
}
}
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("exit nsHTMLFrameOuterFrame::Reflow: size=%d,%d status=%x",
aDesiredSize.width, aDesiredSize.height, aStatus));
@ -876,9 +889,9 @@ nsHTMLFrameInnerFrame::Paint(nsIPresContext* aPresContext,
PRUint32 aFlags)
{
//printf("inner paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x,
//aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); if there is
//not web shell paint based on our background color, otherwise let
//the web shell paint the sub document
//aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
// if there is not web shell paint based on our background color, otherwise
// let the web shell paint the sub document
// isPaginated is a temporary fix for Bug 75737 and this should all
// be fixed correctly by Bug 75739