зеркало из https://github.com/mozilla/pjs.git
Bug 363253. Move scrollframe attribute-setting out of reflow to a post-reflow callback. r+sr=dbaron
This commit is contained in:
Родитель
2444f84d7f
Коммит
d9a0686127
|
@ -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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче