Bug 363253. Move scrollframe attribute-setting out of reflow to a post-reflow callback. r+sr=dbaron

This commit is contained in:
roc+%cs.cmu.edu 2007-03-05 01:39:53 +00:00
Родитель 2444f84d7f
Коммит d9a0686127
9 изменённых файлов: 127 добавлений и 230 удалений

Просмотреть файл

@ -98,10 +98,10 @@ class nsIScrollableFrame;
typedef short SelectionType; typedef short SelectionType;
// e94790d4-e93d-45a9-ab2f-a0c86081abc0 // 7C398278-8523-4E5C-8268-4E4BC8B0C5CA
#define NS_IPRESSHELL_IID \ #define NS_IPRESSHELL_IID \
{ 0xe94790d4, 0xe93d, 0x45a9, \ { 0x7C398278, 0x8523, 0x4E5C, \
{ 0xab, 0x2f, 0xa0, 0xc8, 0x60, 0x81, 0xab, 0xc0 } } { 0x82, 0x68, 0x4E, 0x4B, 0xC8, 0xB0, 0xC5, 0xCA } }
// Constants uses for ScrollFrameIntoView() function // Constants uses for ScrollFrameIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0 #define NS_PRESSHELL_SCROLL_TOP 0
@ -122,12 +122,6 @@ typedef short SelectionType;
#define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40 #define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40
#define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80 #define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80
// for PostAttributeChanged
enum nsAttributeChangeType {
eChangeType_Set = 0, // Set attribute
eChangeType_Remove = 1 // Remove attribute
};
/** /**
* Presentation shell interface. Presentation shells are the * Presentation shell interface. Presentation shells are the
* controlling point for managing the presentation of a document. The * controlling point for managing the presentation of a document. The
@ -389,16 +383,6 @@ public:
*/ */
NS_IMETHOD FlushPendingNotifications(mozFlushType aType) = 0; NS_IMETHOD FlushPendingNotifications(mozFlushType aType) = 0;
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHOD PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType) = 0;
NS_IMETHOD PostReflowCallback(nsIReflowCallback* aCallback) = 0; NS_IMETHOD PostReflowCallback(nsIReflowCallback* aCallback) = 0;
NS_IMETHOD CancelReflowCallback(nsIReflowCallback* aCallback) = 0; NS_IMETHOD CancelReflowCallback(nsIReflowCallback* aCallback) = 0;

Просмотреть файл

@ -38,22 +38,20 @@
#ifndef nsIReflowCallback_h___ #ifndef nsIReflowCallback_h___
#define nsIReflowCallback_h___ #define nsIReflowCallback_h___
// {03E6FD70-889C-44b1-8639-A7EF5A80ED5C}
#define NS_IREFLOWCALLBACK_IID \
{ 0x3e6fd70, 0x889c, 0x44b1, { 0x86, 0x39, 0xa7, 0xef, 0x5a, 0x80, 0xed, 0x5c } }
class nsIPresShell; class nsIPresShell;
/** /**
* Reflow callback interface * Reflow callback interface.
* These are not refcounted. Objects must be removed from the presshell
* callback list before they die.
*/ */
class nsIReflowCallback : public nsISupports { class nsIReflowCallback {
public: public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IREFLOWCALLBACK_IID) /**
* The presshell calls this when reflow has finished. Return PR_TRUE if
NS_IMETHOD ReflowFinished(nsIPresShell* aShell, PRBool* aFlushFlag) = 0; * you need a Flush_Layout to happen after this.
*/
virtual PRBool ReflowFinished() = 0;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(nsIReflowCallback, NS_IREFLOWCALLBACK_IID)
#endif /* nsIFrameUtil_h___ */ #endif /* nsIFrameUtil_h___ */

Просмотреть файл

@ -773,24 +773,6 @@ private:
PRInt32 mCallCount; PRInt32 mCallCount;
}; };
struct nsDOMEventRequest
{
nsIContent* content;
nsEvent* event;
nsDOMEventRequest* next;
};
struct nsAttributeChangeRequest
{
nsIContent* content;
PRInt32 nameSpaceID;
nsIAtom* name;
nsAutoString value;
PRBool notify;
nsAttributeChangeType type;
nsAttributeChangeRequest* next;
};
struct nsCallbackEventRequest struct nsCallbackEventRequest
{ {
nsIReflowCallback* callback; nsIReflowCallback* callback;
@ -862,16 +844,6 @@ public:
*/ */
NS_IMETHOD RecreateFramesFor(nsIContent* aContent); NS_IMETHOD RecreateFramesFor(nsIContent* aContent);
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHOD PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType);
/** /**
* Post a callback that should be handled after reflow has finished. * Post a callback that should be handled after reflow has finished.
*/ */
@ -1042,8 +1014,6 @@ public:
protected: protected:
virtual ~PresShell(); virtual ~PresShell();
void HandlePostedDOMEvents();
void HandlePostedAttributeChanges();
void HandlePostedReflowCallbacks(); void HandlePostedReflowCallbacks();
void UnsuppressAndInvalidate(); void UnsuppressAndInvalidate();
@ -1146,9 +1116,6 @@ protected:
nsRevocableEventPtr<ReflowEvent> mReflowEvent; nsRevocableEventPtr<ReflowEvent> mReflowEvent;
// used for list of posted attribute changes. To be done after reflow.
nsAttributeChangeRequest* mFirstAttributeRequest;
nsAttributeChangeRequest* mLastAttributeRequest;
nsCallbackEventRequest* mFirstCallbackEventRequest; nsCallbackEventRequest* mFirstCallbackEventRequest;
nsCallbackEventRequest* mLastCallbackEventRequest; nsCallbackEventRequest* mLastCallbackEventRequest;
@ -1410,9 +1377,7 @@ PresShell::~PresShell()
NS_ASSERTION(mCurrentEventContentStack.Count() == 0, NS_ASSERTION(mCurrentEventContentStack.Count() == 0,
"Huh, event content left on the stack in pres shell dtor!"); "Huh, event content left on the stack in pres shell dtor!");
NS_ASSERTION(mFirstAttributeRequest == nsnull && NS_ASSERTION(mFirstCallbackEventRequest == nsnull &&
mLastAttributeRequest == nsnull &&
mFirstCallbackEventRequest == nsnull &&
mLastCallbackEventRequest == nsnull, mLastCallbackEventRequest == nsnull,
"post-reflow queues not empty. This means we're leaking"); "post-reflow queues not empty. This means we're leaking");
@ -4422,7 +4387,6 @@ PresShell::PostReflowCallback(nsIReflowCallback* aCallback)
nsCallbackEventRequest* request = (nsCallbackEventRequest*)result; nsCallbackEventRequest* request = (nsCallbackEventRequest*)result;
request->callback = aCallback; request->callback = aCallback;
NS_ADDREF(aCallback);
request->next = nsnull; request->next = nsnull;
if (mLastCallbackEventRequest) { if (mLastCallbackEventRequest) {
@ -4461,7 +4425,6 @@ PresShell::CancelReflowCallback(nsIReflowCallback* aCallback)
} }
FreeFrame(sizeof(nsCallbackEventRequest), toFree); FreeFrame(sizeof(nsCallbackEventRequest), toFree);
NS_RELEASE(callback);
} else { } else {
before = node; before = node;
node = node->next; node = node->next;
@ -4471,47 +4434,6 @@ PresShell::CancelReflowCallback(nsIReflowCallback* aCallback)
return NS_OK; return NS_OK;
} }
/**
* Post a request to set and attribute after reflow has finished.
*/
NS_IMETHODIMP
PresShell::PostAttributeChange(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue,
PRBool aNotify,
nsAttributeChangeType aType)
{
// ok we have a list of events to handle. Queue them up and handle them
// after we finish reflow.
void* result = AllocateFrame(sizeof(nsAttributeChangeRequest));
if (NS_UNLIKELY(!result)) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsAttributeChangeRequest* request = new (result) nsAttributeChangeRequest();
request->content = aContent;
NS_ADDREF(aContent);
request->nameSpaceID = aNameSpaceID;
request->name = aName;
request->value = aValue;
request->notify = aNotify;
request->type = aType;
request->next = nsnull;
if (mLastAttributeRequest) {
mLastAttributeRequest = mLastAttributeRequest->next = request;
} else {
mFirstAttributeRequest = request;
mLastAttributeRequest = request;
}
return NS_OK;
}
void void
PresShell::HandlePostedReflowCallbacks() PresShell::HandlePostedReflowCallbacks()
{ {
@ -4525,40 +4447,17 @@ PresShell::HandlePostedReflowCallbacks()
} }
nsIReflowCallback* callback = node->callback; nsIReflowCallback* callback = node->callback;
FreeFrame(sizeof(nsCallbackEventRequest), node); FreeFrame(sizeof(nsCallbackEventRequest), node);
if (callback) if (callback) {
callback->ReflowFinished(this, &shouldFlush); if (callback->ReflowFinished()) {
NS_IF_RELEASE(callback); shouldFlush = PR_TRUE;
}
}
} }
if (shouldFlush) if (shouldFlush)
FlushPendingNotifications(Flush_Layout); FlushPendingNotifications(Flush_Layout);
} }
void
PresShell::HandlePostedAttributeChanges()
{
while(mFirstAttributeRequest)
{
/* pull the node from the request list. Be prepared for reentrant access to the list
from within SetAttribute/UnsetAttribute and its callees! */
nsAttributeChangeRequest* node = mFirstAttributeRequest;
mFirstAttributeRequest = node->next;
if (nsnull == mFirstAttributeRequest) {
mLastAttributeRequest = nsnull;
}
if (node->type == eChangeType_Set)
node->content->SetAttr(node->nameSpaceID, node->name, node->value, node->notify);
else
node->content->UnsetAttr(node->nameSpaceID, node->name, node->notify);
NS_RELEASE(node->content);
node->nsAttributeChangeRequest::~nsAttributeChangeRequest();
FreeFrame(sizeof(nsAttributeChangeRequest), node);
}
}
NS_IMETHODIMP NS_IMETHODIMP
PresShell::IsSafeToFlush(PRBool& aIsSafeToFlush) PresShell::IsSafeToFlush(PRBool& aIsSafeToFlush)
{ {
@ -5840,7 +5739,6 @@ PresShell::WillDoReflow()
void void
PresShell::DidDoReflow() PresShell::DidDoReflow()
{ {
HandlePostedAttributeChanges();
HandlePostedReflowCallbacks(); HandlePostedReflowCallbacks();
// Null-check mViewManager in case this happens during Destroy. See // Null-check mViewManager in case this happens during Destroy. See
// bugs 244435 and 238546. // bugs 244435 and 238546.

Просмотреть файл

@ -153,12 +153,6 @@ nsHTMLScrollFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
void void
nsHTMLScrollFrame::Destroy() nsHTMLScrollFrame::Destroy()
{ {
mInner.mScrollEvent.Revoke();
mInner.mAsyncScrollPortEvent.Revoke();
nsIScrollableView *view = mInner.GetScrollableView();
NS_ASSERTION(view, "unexpected null pointer");
if (view)
view->RemoveScrollPositionListener(&mInner);
mInner.Destroy(); mInner.Destroy();
nsHTMLContainerFrame::Destroy(); nsHTMLContainerFrame::Destroy();
} }
@ -965,12 +959,6 @@ nsXULScrollFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
void void
nsXULScrollFrame::Destroy() nsXULScrollFrame::Destroy()
{ {
mInner.mScrollEvent.Revoke();
mInner.mAsyncScrollPortEvent.Revoke();
nsIScrollableView *view = mInner.GetScrollableView();
NS_ASSERTION(view, "unexpected null pointer");
if (view)
view->RemoveScrollPositionListener(&mInner);
mInner.Destroy(); mInner.Destroy();
nsBoxFrame::Destroy(); nsBoxFrame::Destroy();
} }
@ -1248,7 +1236,8 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsContainerFrame* aOuter,
mHistoryVScrollbarHint(PR_FALSE), mHistoryVScrollbarHint(PR_FALSE),
mHadNonInitialReflow(PR_FALSE), mHadNonInitialReflow(PR_FALSE),
mHorizontalOverflow(PR_FALSE), mHorizontalOverflow(PR_FALSE),
mVerticalOverflow(PR_FALSE) mVerticalOverflow(PR_FALSE),
mPostedReflowCallback(PR_FALSE)
{ {
} }
@ -1718,6 +1707,17 @@ nsGfxScrollFrameInner::Destroy()
nsContentUtils::DestroyAnonymousContent(&mHScrollbarContent); nsContentUtils::DestroyAnonymousContent(&mHScrollbarContent);
nsContentUtils::DestroyAnonymousContent(&mVScrollbarContent); nsContentUtils::DestroyAnonymousContent(&mVScrollbarContent);
nsContentUtils::DestroyAnonymousContent(&mScrollCornerContent); nsContentUtils::DestroyAnonymousContent(&mScrollCornerContent);
mScrollEvent.Revoke();
mAsyncScrollPortEvent.Revoke();
if (mPostedReflowCallback) {
mOuter->GetPresContext()->PresShell()->CancelReflowCallback(this);
mPostedReflowCallback = PR_FALSE;
}
nsIScrollableView *view = GetScrollableView();
NS_ASSERTION(view, "unexpected null pointer");
if (view)
view->RemoveScrollPositionListener(this);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -2302,16 +2302,17 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState)
return NS_OK; return NS_OK;
} }
void PRBool
nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState, nsGfxScrollFrameInner::ReflowFinished()
const nsRect& aContentArea,
const nsRect& aOldScrollArea,
const nsRect& aScrollArea)
{ {
NS_ASSERTION(!mSupppressScrollbarUpdate, mPostedReflowCallback = PR_FALSE;
"This should have been suppressed");
// Update scrollbar attributes.
nsPresContext* presContext = aState.PresContext(); nsPresContext* presContext = mOuter->GetPresContext();
nsIScrollableView* scrollable = GetScrollableView();
nsRect scrollArea = scrollable->View()->GetBounds();
const nsStyleFont* font = mOuter->GetStyleFont(); const nsStyleFont* font = mOuter->GetStyleFont();
const nsFont& f = font->mFont; const nsFont& f = font->mFont;
nsCOMPtr<nsIFontMetrics> fm = presContext->GetMetricsFor(f); nsCOMPtr<nsIFontMetrics> fm = presContext->GetMetricsFor(f);
@ -2319,20 +2320,16 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
NS_ASSERTION(fm,"FontMetrics is null assuming fontHeight == 1"); NS_ASSERTION(fm,"FontMetrics is null assuming fontHeight == 1");
if (fm) if (fm)
fm->GetHeight(fontHeight); fm->GetHeight(fontHeight);
nsRect scrolledContentRect = GetScrolledRect(aScrollArea.Size());
nscoord minX = scrolledContentRect.x;
nscoord maxX = scrolledContentRect.XMost() - aScrollArea.width;
nscoord minY = scrolledContentRect.y;
nscoord maxY = scrolledContentRect.YMost() - aScrollArea.height;
nsIScrollableView* scrollable = GetScrollableView();
scrollable->SetLineHeight(fontHeight); scrollable->SetLineHeight(fontHeight);
nsRect scrolledContentRect = GetScrolledRect(scrollArea.Size());
nscoord minX = scrolledContentRect.x;
nscoord maxX = scrolledContentRect.XMost() - scrollArea.width;
nscoord minY = scrolledContentRect.y;
nscoord maxY = scrolledContentRect.YMost() - scrollArea.height;
// Suppress handling of the curpos attribute changes we make here. // Suppress handling of the curpos attribute changes we make here.
PRBool oldFrameInitiatedScroll = mFrameInitiatedScroll; NS_ASSERTION(!mFrameInitiatedScroll, "We shouldn't be reentering here");
mFrameInitiatedScroll = PR_TRUE; mFrameInitiatedScroll = PR_TRUE;
if (mVScrollbarBox) { if (mVScrollbarBox) {
@ -2343,18 +2340,10 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
SetCoordAttribute(mVScrollbarBox, nsGkAtoms::curpos, curPosY - minY); SetCoordAttribute(mVScrollbarBox, nsGkAtoms::curpos, curPosY - minY);
SetScrollbarEnabled(mVScrollbarBox, maxY - minY); SetScrollbarEnabled(mVScrollbarBox, maxY - minY);
SetCoordAttribute(mVScrollbarBox, nsGkAtoms::maxpos, maxY - minY); SetCoordAttribute(mVScrollbarBox, nsGkAtoms::maxpos, maxY - minY);
SetCoordAttribute(mVScrollbarBox, nsGkAtoms::pageincrement, nscoord(aScrollArea.height - fontHeight)); SetCoordAttribute(mVScrollbarBox, nsGkAtoms::pageincrement, nscoord(scrollArea.height - fontHeight));
SetCoordAttribute(mVScrollbarBox, nsGkAtoms::increment, fontHeight); SetCoordAttribute(mVScrollbarBox, nsGkAtoms::increment, fontHeight);
nsRect vRect(aScrollArea);
vRect.width = aContentArea.width - aScrollArea.width;
vRect.x = IsScrollbarOnRight() ? aScrollArea.XMost() : aContentArea.x;
nsMargin margin;
mVScrollbarBox->GetMargin(margin);
vRect.Deflate(margin);
nsBoxFrame::LayoutChildAt(aState, mVScrollbarBox, vRect);
} }
if (mHScrollbarBox) { if (mHScrollbarBox) {
NS_PRECONDITION(mHScrollbarBox->IsBoxFrame(), "Must be a box frame!"); NS_PRECONDITION(mHScrollbarBox->IsBoxFrame(), "Must be a box frame!");
nscoord curPosX, curPosY; nscoord curPosX, curPosY;
@ -2363,19 +2352,11 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
SetCoordAttribute(mHScrollbarBox, nsGkAtoms::curpos, curPosX - minX); SetCoordAttribute(mHScrollbarBox, nsGkAtoms::curpos, curPosX - minX);
SetScrollbarEnabled(mHScrollbarBox, maxX - minX); SetScrollbarEnabled(mHScrollbarBox, maxX - minX);
SetCoordAttribute(mHScrollbarBox, nsGkAtoms::maxpos, maxX - minX); SetCoordAttribute(mHScrollbarBox, nsGkAtoms::maxpos, maxX - minX);
SetCoordAttribute(mHScrollbarBox, nsGkAtoms::pageincrement, nscoord(float(aScrollArea.width)*0.8)); SetCoordAttribute(mHScrollbarBox, nsGkAtoms::pageincrement, nscoord(float(scrollArea.width)*0.8));
SetCoordAttribute(mHScrollbarBox, nsGkAtoms::increment, nsPresContext::CSSPixelsToAppUnits(10)); SetCoordAttribute(mHScrollbarBox, nsGkAtoms::increment, nsPresContext::CSSPixelsToAppUnits(10));
nsRect hRect(aScrollArea);
hRect.height = aContentArea.height - aScrollArea.height;
hRect.y = PR_TRUE ? aScrollArea.YMost() : aContentArea.y;
nsMargin margin;
mHScrollbarBox->GetMargin(margin);
hRect.Deflate(margin);
nsBoxFrame::LayoutChildAt(aState, mHScrollbarBox, hRect);
} }
mFrameInitiatedScroll = oldFrameInitiatedScroll; mFrameInitiatedScroll = PR_FALSE;
// We used to rely on the curpos attribute changes above to scroll the // We used to rely on the curpos attribute changes above to scroll the
// view. However, for scrolling to the left of the viewport, we // view. However, for scrolling to the left of the viewport, we
// rescale the curpos attribute, which means that operations like // rescale the curpos attribute, which means that operations like
@ -2387,9 +2368,43 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
// nsSliderFrame::AttributeChanged's handling of maxpos, but not when // nsSliderFrame::AttributeChanged's handling of maxpos, but not when
// we hide the scrollbar on a large size change, such as // we hide the scrollbar on a large size change, such as
// maximization.) // maximization.)
if (mHScrollbarBox || mVScrollbarBox) if (!mHScrollbarBox && !mVScrollbarBox)
CurPosAttributeChanged(mVScrollbarBox ? mVScrollbarBox->GetContent() return PR_FALSE;
: mHScrollbarBox->GetContent()); CurPosAttributeChanged(mVScrollbarBox ? mVScrollbarBox->GetContent()
: mHScrollbarBox->GetContent());
return PR_TRUE;
}
void
nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
const nsRect& aContentArea,
const nsRect& aOldScrollArea,
const nsRect& aScrollArea)
{
NS_ASSERTION(!mSupppressScrollbarUpdate,
"This should have been suppressed");
if (mVScrollbarBox) {
NS_PRECONDITION(mVScrollbarBox->IsBoxFrame(), "Must be a box frame!");
nsRect vRect(aScrollArea);
vRect.width = aContentArea.width - aScrollArea.width;
vRect.x = IsScrollbarOnRight() ? aScrollArea.XMost() : aContentArea.x;
nsMargin margin;
mVScrollbarBox->GetMargin(margin);
vRect.Deflate(margin);
nsBoxFrame::LayoutChildAt(aState, mVScrollbarBox, vRect);
}
if (mHScrollbarBox) {
NS_PRECONDITION(mHScrollbarBox->IsBoxFrame(), "Must be a box frame!");
nsRect hRect(aScrollArea);
hRect.height = aContentArea.height - aScrollArea.height;
hRect.y = PR_TRUE ? aScrollArea.YMost() : aContentArea.y;
nsMargin margin;
mHScrollbarBox->GetMargin(margin);
hRect.Deflate(margin);
nsBoxFrame::LayoutChildAt(aState, mHScrollbarBox, hRect);
}
// place the scrollcorner // place the scrollcorner
if (mScrollCornerBox) { if (mScrollCornerBox) {
@ -2434,10 +2449,16 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
// force a reflow of the fixed child // force a reflow of the fixed child
fixedChild->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); fixedChild->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
// XXX Will this work given where we currently are in reflow? // XXX Will this work given where we currently are in reflow?
mOuter->GetPresContext()->PresShell()-> aState.PresContext()->PresShell()->
FrameNeedsReflow(fixedChild, nsIPresShell::eResize); FrameNeedsReflow(fixedChild, nsIPresShell::eResize);
} }
} }
// post reflow callback to modify scrollbar attributes
if (!mPostedReflowCallback) {
aState.PresContext()->PresShell()->PostReflowCallback(this);
mPostedReflowCallback = PR_TRUE;
}
} }
void void
@ -2449,38 +2470,34 @@ nsGfxScrollFrameInner::ScrollbarChanged(nsPresContext* aPresContext, nscoord aX,
} }
void void
nsGfxScrollFrameInner::SetScrollbarEnabled(nsIBox* aBox, nscoord aMaxPos, PRBool aReflow) nsGfxScrollFrameInner::SetScrollbarEnabled(nsIBox* aBox, nscoord aMaxPos)
{ {
mOuter->GetPresContext()->PresShell()->PostAttributeChange( nsIContent* content = aBox->GetContent();
aBox->GetContent(), if (aMaxPos) {
kNameSpaceID_None, content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, PR_TRUE);
nsGkAtoms::disabled, } else {
NS_LITERAL_STRING("true"), content->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
aReflow, NS_LITERAL_STRING("true"), PR_TRUE);
aMaxPos ? eChangeType_Remove : eChangeType_Set); }
} }
/** void
* Returns whether it actually needed to change the attribute nsGfxScrollFrameInner::SetCoordAttribute(nsIBox* aBox, nsIAtom* aAtom,
*/ nscoord aSize)
PRBool
nsGfxScrollFrameInner::SetCoordAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow)
{ {
// convert to pixels // convert to pixels
aSize = nsPresContext::AppUnitsToIntCSSPixels(aSize); aSize = nsPresContext::AppUnitsToIntCSSPixels(aSize);
// only set the attribute if it changed. // only set the attribute if it changed.
nsIContent *content = aBox->GetContent();
nsAutoString newValue; nsAutoString newValue;
newValue.AppendInt(aSize); newValue.AppendInt(aSize);
nsIContent* content = aBox->GetContent();
if (content->AttrValueIs(kNameSpaceID_None, aAtom, newValue, eCaseMatters)) if (content->AttrValueIs(kNameSpaceID_None, aAtom, newValue, eCaseMatters))
return PR_FALSE; return;
content->SetAttr(kNameSpaceID_None, aAtom, newValue, aReflow); content->SetAttr(kNameSpaceID_None, aAtom, newValue, PR_TRUE);
return PR_TRUE;
} }
nsRect nsRect

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsIScrollableView.h" #include "nsIScrollableView.h"
#include "nsIView.h" #include "nsIView.h"
#include "nsIReflowCallback.h"
class nsPresContext; class nsPresContext;
class nsIPresShell; class nsIPresShell;
@ -60,7 +61,8 @@ class nsIScrollFrameInternal;
class nsPresState; class nsPresState;
struct ScrollReflowState; struct ScrollReflowState;
class nsGfxScrollFrameInner : public nsIScrollPositionListener { class nsGfxScrollFrameInner : public nsIScrollPositionListener,
public nsIReflowCallback {
public: public:
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void); NS_IMETHOD_(nsrefcnt) AddRef(void);
@ -92,6 +94,9 @@ public:
virtual void InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY, virtual void InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
nsIFrame* aForChild, PRBool aImmediate); nsIFrame* aForChild, PRBool aImmediate);
// nsIReflowCallback
virtual PRBool ReflowFinished();
// nsIScrollPositionListener // nsIScrollPositionListener
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
@ -120,8 +125,8 @@ public:
nsGfxScrollFrameInner *mInner; nsGfxScrollFrameInner *mInner;
}; };
void SetScrollbarEnabled(nsIBox* aBox, nscoord aMaxPos, PRBool aReflow=PR_TRUE); void SetScrollbarEnabled(nsIBox* aBox, nscoord aMaxPos);
PRBool SetCoordAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); void SetCoordAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize);
nscoord GetCoordAttribute(nsIBox* aFrame, nsIAtom* atom, nscoord defaultValue); nscoord GetCoordAttribute(nsIBox* aFrame, nsIAtom* atom, nscoord defaultValue);
// Like ScrollPositionDidChange, but initiated by this frame rather than from the // Like ScrollPositionDidChange, but initiated by this frame rather than from the
@ -218,6 +223,7 @@ public:
// which overflow states have changed. // which overflow states have changed.
PRPackedBool mHorizontalOverflow:1; PRPackedBool mHorizontalOverflow:1;
PRPackedBool mVerticalOverflow:1; PRPackedBool mVerticalOverflow:1;
PRPackedBool mPostedReflowCallback:1;
}; };
/** /**

Просмотреть файл

@ -226,7 +226,6 @@ nsListBoxBodyFrame::Release(void)
NS_INTERFACE_MAP_BEGIN(nsListBoxBodyFrame) NS_INTERFACE_MAP_BEGIN(nsListBoxBodyFrame)
NS_INTERFACE_MAP_ENTRY(nsIListBoxObject) NS_INTERFACE_MAP_ENTRY(nsIListBoxObject)
NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator) NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator)
NS_INTERFACE_MAP_ENTRY(nsIReflowCallback)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
@ -487,8 +486,8 @@ nsListBoxBodyFrame::ScrollbarButtonPressed(nsISupports* aScrollbar, PRInt32 aOld
///////////// nsIReflowCallback /////////////// ///////////// nsIReflowCallback ///////////////
NS_IMETHODIMP PRBool
nsListBoxBodyFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag) nsListBoxBodyFrame::ReflowFinished()
{ {
// now create or destroy any rows as needed // now create or destroy any rows as needed
CreateRows(); CreateRows();
@ -512,9 +511,7 @@ nsListBoxBodyFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag)
} }
mReflowCallbackPosted = PR_FALSE; mReflowCallbackPosted = PR_FALSE;
*aFlushFlag = PR_TRUE; return PR_TRUE;
return NS_OK;
} }
///////// nsIListBoxObject /////////////// ///////// nsIListBoxObject ///////////////

Просмотреть файл

@ -86,7 +86,7 @@ public:
NS_IMETHOD VisibilityChanged(nsISupports* aScrollbar, PRBool aVisible); NS_IMETHOD VisibilityChanged(nsISupports* aScrollbar, PRBool aVisible);
// nsIReflowCallback // nsIReflowCallback
NS_IMETHOD ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag); virtual PRBool ReflowFinished();
// nsIBox // nsIBox
NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState); NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);

Просмотреть файл

@ -138,7 +138,6 @@ NS_INTERFACE_MAP_BEGIN(nsTreeBodyFrame)
NS_INTERFACE_MAP_ENTRY(nsITreeBoxObject) NS_INTERFACE_MAP_ENTRY(nsITreeBoxObject)
NS_INTERFACE_MAP_ENTRY(nsICSSPseudoComparator) NS_INTERFACE_MAP_ENTRY(nsICSSPseudoComparator)
NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator) NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator)
NS_INTERFACE_MAP_ENTRY(nsIReflowCallback)
NS_INTERFACE_MAP_END_INHERITING(nsLeafBoxFrame) NS_INTERFACE_MAP_END_INHERITING(nsLeafBoxFrame)
@ -418,8 +417,8 @@ nsTreeBodyFrame::SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRec
} }
NS_IMETHODIMP PRBool
nsTreeBodyFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag) nsTreeBodyFrame::ReflowFinished()
{ {
if (mView) { if (mView) {
CalcInnerBox(); CalcInnerBox();
@ -449,9 +448,7 @@ nsTreeBodyFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag)
} }
mReflowCallbackPosted = PR_FALSE; mReflowCallbackPosted = PR_FALSE;
*aFlushFlag = PR_FALSE; return PR_FALSE;
return NS_OK;
} }

Просмотреть файл

@ -91,7 +91,7 @@ public:
PRBool aRemoveOverflowArea = PR_FALSE); PRBool aRemoveOverflowArea = PR_FALSE);
// nsIReflowCallback // nsIReflowCallback
NS_IMETHOD ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag); virtual PRBool ReflowFinished();
// nsICSSPseudoComparator // nsICSSPseudoComparator
NS_IMETHOD PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBool* aResult); NS_IMETHOD PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBool* aResult);