Bug 257916. Move history scroll position save and restore from nsScrollBoxFrame to nsHTML/XULScrollFrame. +sr=dbaron(rubber-stamp)

This commit is contained in:
roc+%cs.cmu.edu 2004-09-13 02:10:29 +00:00
Родитель ce80d8481f
Коммит cdaf90f7e4
12 изменённых файлов: 497 добавлений и 537 удалений

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

@ -3511,14 +3511,8 @@ PresShell::EndLoad(nsIDocument *aDocument)
CallQueryInterface(scrollFrame, &scrollableFrame);
NS_ASSERTION(scrollableFrame, "RootScrollFrame is not scrollable?");
if (scrollableFrame) {
// XXX We shouldn't depend on the scrolling guts here. Make this
// go away!
nsIFrame* scrollBoxFrame = scrollFrame->GetFirstChild(nsnull);
if (scrollBoxFrame) {
FrameManager()->RestoreFrameStateFor(scrollBoxFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
}
FrameManager()->RestoreFrameStateFor(scrollFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
scrollableFrame->ScrollToRestoredPosition();
}
}
@ -4503,13 +4497,8 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
if (aLeavingPage) {
nsIFrame* scrollFrame = GetRootScrollFrame(rootFrame);
if (scrollFrame) {
// XXX We shouldn't depend on the scrolling guts here. Make this
// go away!
nsIFrame* scrollBoxFrame = scrollFrame->GetFirstChild(nsnull);
if (scrollBoxFrame) {
FrameManager()->CaptureFrameStateFor(scrollBoxFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
}
FrameManager()->CaptureFrameStateFor(scrollFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
}
}

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

@ -294,6 +294,7 @@ nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
mIsAllFramesHere = PR_FALSE;
mHasBeenInitialized = PR_FALSE;
mNeedToReset = PR_TRUE;
mPostChildrenLoadedReset = PR_FALSE;
mCacheSize.width = -1;
mCacheSize.height = -1;
@ -558,129 +559,9 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
*aInstancePtr = (void *)((nsISelectControlFrame*)this);
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) {
*aInstancePtr =
NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIStatefulFrame*,this));
return NS_OK;
}
return nsHTMLScrollFrame::QueryInterface(aIID, aInstancePtr);
}
//----------------------------------------------------------------------
// nsIStatefulFrame
// These methods were originally in the nsScrollFrame superclass,
// but were moved here when nsListControlFrame switched to use
// nsHTMLScrollFrame.
//----------------------------------------------------------------------
NS_IMETHODIMP
nsListControlFrame::SaveState(nsPresContext* aPresContext,
nsIPresState** aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsCOMPtr<nsIPresState> state;
nsresult res = NS_OK;
nsIScrollableView* scrollingView = GetScrollableView();
nscoord x = 0, y = 0;
if (scrollingView) {
scrollingView->GetScrollPosition(x, y);
}
// Don't save scroll position if we are at (0,0)
if (x || y) {
nsIView* child = nsnull;
scrollingView->GetScrolledView(child);
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
nsRect childRect = child->GetBounds();
res = NS_NewPresState(getter_AddRefs(state));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsISupportsPRInt32> xoffset =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (xoffset) {
res = xoffset->SetData(x);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), xoffset);
}
nsCOMPtr<nsISupportsPRInt32> yoffset =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (yoffset) {
res = yoffset->SetData(y);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), yoffset);
}
nsCOMPtr<nsISupportsPRInt32> width =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (width) {
res = width->SetData(childRect.width);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("width"), width);
}
nsCOMPtr<nsISupportsPRInt32> height =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (height) {
res = height->SetData(childRect.height);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("height"), height);
}
*aState = state;
NS_ADDREF(*aState);
}
return res;
}
//-----------------------------------------------------------
NS_IMETHODIMP
nsListControlFrame::RestoreState(nsPresContext* aPresContext,
nsIPresState* aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsCOMPtr<nsISupportsPRInt32> width;
nsCOMPtr<nsISupportsPRInt32> height;
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), getter_AddRefs(xoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), getter_AddRefs(yoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("width"), getter_AddRefs(width));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("height"), getter_AddRefs(height));
nsresult res = NS_ERROR_NULL_POINTER;
if (xoffset && yoffset) {
PRInt32 x,y,w,h;
res = xoffset->GetData(&x);
if (NS_SUCCEEDED(res))
res = yoffset->GetData(&y);
if (NS_SUCCEEDED(res))
res = width->GetData(&w);
if (NS_SUCCEEDED(res))
res = height->GetData(&h);
if (NS_SUCCEEDED(res)) {
nsIScrollableView* scrollingView = GetScrollableView();
if (scrollingView) {
nsIView* child = nsnull;
nsRect childRect(0,0,0,0);
if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) {
childRect = child->GetBounds();
}
x = (int)(((float)childRect.width / w) * x);
y = (int)(((float)childRect.height / h) * y);
scrollingView->ScrollTo(x,y,0);
}
}
}
return res;
}
#ifdef ACCESSIBILITY
NS_IMETHODIMP nsListControlFrame::GetAccessible(nsIAccessible** aAccessible)
{
@ -1885,7 +1766,7 @@ nsListControlFrame::MouseClicked(nsPresContext* aPresContext)
NS_IMETHODIMP
nsListControlFrame::OnContentReset()
{
ResetList();
ResetList(PR_TRUE);
return NS_OK;
}
@ -1894,7 +1775,7 @@ nsListControlFrame::OnContentReset()
// those values as determined by the original HTML
//---------------------------------------------------------
void
nsListControlFrame::ResetList()
nsListControlFrame::ResetList(PRBool aAllowScrolling)
{
REFLOW_DEBUG_MSG("LBX::ResetList\n");
@ -1904,14 +1785,18 @@ nsListControlFrame::ResetList()
return;
}
// Scroll to the selected index
PRInt32 indexToSelect = kNothingSelected;
if (aAllowScrolling) {
mPostChildrenLoadedReset = PR_TRUE;
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(mContent));
NS_ASSERTION(selectElement, "No select element!");
if (selectElement) {
selectElement->GetSelectedIndex(&indexToSelect);
ScrollToIndex(indexToSelect);
// Scroll to the selected index
PRInt32 indexToSelect = kNothingSelected;
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(mContent));
NS_ASSERTION(selectElement, "No select element!");
if (selectElement) {
selectElement->GetSelectedIndex(&indexToSelect);
ScrollToIndex(indexToSelect);
}
}
mStartSelectionIndex = kNothingSelected;
@ -2095,7 +1980,7 @@ nsListControlFrame::DoneAddingChildren(PRBool aIsDone)
// if all the frames are now present we can initalize
if (CheckIfAllFramesHere()) {
mHasBeenInitialized = PR_TRUE;
ResetList();
ResetList(PR_TRUE);
}
}
}
@ -2129,6 +2014,7 @@ nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
// Make sure we scroll to the selected option as needed
mNeedToReset = PR_TRUE;
mPostChildrenLoadedReset = mIsAllContentHere;
return NS_OK;
}
@ -2139,6 +2025,7 @@ nsListControlFrame::RemoveOption(nsPresContext* aPresContext, PRInt32 aIndex)
// Need to reset if we're a dropdown
if (IsInDropDownMode()) {
mNeedToReset = PR_TRUE;
mPostChildrenLoadedReset = mIsAllContentHere;
}
return NS_OK;
@ -2444,7 +2331,16 @@ nsListControlFrame::DidReflow(nsPresContext* aPresContext,
if (mNeedToReset) {
mNeedToReset = PR_FALSE;
ResetList();
// Suppress scrolling to the selected element if we restored
// scroll history state AND the list contents have not changed
// since we loaded all the children AND nothing else forced us
// to scroll by calling ResetList(PR_TRUE). The latter two conditions
// are folded into mPostChildrenLoadedReset.
//
// The idea is that we want scroll history restoration to trump ResetList
// scrolling to the selected element, when the ResetList was probably only
// caused by content loading normally.
ResetList(!DidHistoryRestore() || mPostChildrenLoadedReset);
}
return rv;
@ -2841,6 +2737,8 @@ nsresult
nsListControlFrame::ScrollToIndex(PRInt32 aIndex)
{
if (aIndex < 0) {
// XXX shouldn't we just do nothing if we're asked to scroll to
// kNothingSelected?
return ScrollToFrame(nsnull);
} else {
nsCOMPtr<nsIContent> content = getter_AddRefs(GetOptionContent(aIndex));

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

@ -52,7 +52,6 @@
#include "nsIFormControlFrame.h"
#include "nsIListControlFrame.h"
#include "nsISelectControlFrame.h"
#include "nsIStatefulFrame.h"
#include "nsIDOMEventListener.h"
#include "nsIPresState.h"
#include "nsIContent.h"
@ -77,7 +76,6 @@ class nsListEventListener;
class nsListControlFrame : public nsHTMLScrollFrame,
public nsIFormControlFrame,
public nsIListControlFrame,
public nsIStatefulFrame,
public nsISelectControlFrame
{
public:
@ -190,10 +188,6 @@ public:
NS_IMETHOD GetDummyFrame(nsIFrame** aFrame);
NS_IMETHOD SetDummyFrame(nsIFrame* aFrame);
//nsIStatefulFrame
NS_IMETHOD SaveState(nsPresContext* aPresContext, nsIPresState** aState);
NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsIPresState* aState);
// mouse event listeners
nsresult MouseDown(nsIDOMEvent* aMouseEvent);
nsresult MouseUp(nsIDOMEvent* aMouseEvent);
@ -231,7 +225,7 @@ protected:
PRBool IsClickingInCombobox(nsIDOMEvent* aMouseEvent);
void AdjustIndexForDisabledOpt(PRInt32 aStartIndex, PRInt32 &anNewIndex,
PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext);
virtual void ResetList();
virtual void ResetList(PRBool aAllowScrolling);
nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument);
virtual ~nsListControlFrame();
@ -282,6 +276,7 @@ protected:
PRPackedBool mIsAllFramesHere;
PRPackedBool mHasBeenInitialized;
PRPackedBool mNeedToReset;
PRPackedBool mPostChildrenLoadedReset;
PRPackedBool mOverrideReflowOpt;

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

@ -70,6 +70,7 @@
#include "nsIURI.h"
#include "nsGUIEvent.h"
#include "nsContentCreatorFunctions.h"
#include "nsISupportsPrimitives.h"
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#endif
@ -606,6 +607,7 @@ NS_INTERFACE_MAP_BEGIN(nsHTMLScrollFrame)
#endif
NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame)
NS_INTERFACE_MAP_ENTRY(nsIScrollableViewProvider)
NS_INTERFACE_MAP_ENTRY(nsIStatefulFrame)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
//----------nsXULScrollFrame-------------------------------------------
@ -1119,6 +1121,7 @@ NS_INTERFACE_MAP_BEGIN(nsXULScrollFrame)
#endif
NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame)
NS_INTERFACE_MAP_ENTRY(nsIScrollableViewProvider)
NS_INTERFACE_MAP_ENTRY(nsIStatefulFrame)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
@ -1133,16 +1136,16 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsBoxFrame* aOuter)
mOnePixel(20),
mOuter(aOuter),
mMaxElementWidth(0),
mRestoreRect(-1, -1, -1, -1),
mLastPos(-1, -1),
mLastDir(-1),
mNeverHasVerticalScrollbar(PR_FALSE),
mNeverHasHorizontalScrollbar(PR_FALSE),
mHasVerticalScrollbar(PR_FALSE),
mHasHorizontalScrollbar(PR_FALSE),
mFirstPass(PR_FALSE),
mIsRoot(PR_FALSE),
mNeverReflowed(PR_TRUE),
mViewInitiatedScroll(PR_FALSE),
mFrameInitiatedScroll(PR_FALSE)
mFrameInitiatedScroll(PR_FALSE),
mDidHistoryRestore(PR_FALSE)
{
}
@ -1208,10 +1211,65 @@ nsGfxScrollFrameInner::GetScrollbarStylesFromFrame() const
return result;
}
/**
* this code is resposible for restoring the scroll position back to some
* saved positon. if the user has not moved the scroll position manually
* we keep scrolling down until we get to our orignally position. keep in
* mind that content could incrementally be coming in. we only want to stop
* when we reach our new position.
*/
void
nsGfxScrollFrameInner::ScrollToRestoredPosition()
{
NS_STATIC_CAST(nsScrollBoxFrame*, mScrollAreaBox)->ScrollToRestoredPosition();
nsIScrollableView* scrollingView = GetScrollableView();
if (!scrollingView) {
return;
}
if (mRestoreRect.y == -1 || mLastPos.x == -1 || mLastPos.y == -1) {
return;
}
// make sure our scroll position did not change for where we last put
// it. if it does then the user must have moved it, and we no longer
// need to restore.
nscoord x = 0;
nscoord y = 0;
scrollingView->GetScrollPosition(x, y);
// if we didn't move, we still need to restore
if (x == mLastPos.x && y == mLastPos.y) {
nsRect childRect(0, 0, 0, 0);
nsIView* child = nsnull;
nsresult rv = scrollingView->GetScrolledView(child);
if (NS_SUCCEEDED(rv) && child)
childRect = child->GetBounds();
PRInt32 cx, cy, x, y;
scrollingView->GetScrollPosition(cx,cy);
x = (int)
(((float)childRect.width / mRestoreRect.width) * mRestoreRect.x);
y = (int)
(((float)childRect.height / mRestoreRect.height) * mRestoreRect.y);
// if our position is greater than the scroll position, scroll.
// remember that we could be incrementally loading so we may enter
// and scroll many times.
if (y > cy || x > cx) {
scrollingView->ScrollTo(x, y, 0);
// scrollpostion goes from twips to pixels. this fixes any roundoff
// problems.
scrollingView->GetScrollPosition(mLastPos.x, mLastPos.y);
} else {
// if we reached the position then stop
mRestoreRect.y = -1;
mLastPos.x = -1;
mLastPos.y = -1;
}
} else {
// user moved the position, so we won't need to restore
mLastPos.x = -1;
mLastPos.y = -1;
}
}
void
@ -2032,6 +2090,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
}
}
ScrollToRestoredPosition();
return NS_OK;
}
@ -2135,3 +2195,111 @@ nsGfxScrollFrameInner::GetIntegerAttribute(nsIBox* aBox, nsIAtom* atom, PRInt32
return defaultValue;
}
already_AddRefed<nsIPresState>
nsGfxScrollFrameInner::SaveState()
{
nsCOMPtr<nsIScrollbarMediator> mediator;
nsIFrame* first = GetScrolledFrame();
mediator = do_QueryInterface(first);
if (mediator) {
// Child manages its own scrolling. Bail.
return nsnull;
}
nsIScrollableView* scrollingView = GetScrollableView();
PRInt32 x,y;
scrollingView->GetScrollPosition(x,y);
// Don't save scroll position if we are at (0,0)
if (!x && !y) {
return nsnull;
}
nsIView* child = nsnull;
scrollingView->GetScrolledView(child);
if (!child) {
return nsnull;
}
nsRect childRect = child->GetBounds();
nsCOMPtr<nsIPresState> state;
nsresult rv = NS_NewPresState(getter_AddRefs(state));
NS_ENSURE_SUCCESS(rv, nsnull);
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(xoffset));
if (xoffset) {
rv = xoffset->SetData(x);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), xoffset);
}
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(yoffset));
if (yoffset) {
rv = yoffset->SetData(y);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), yoffset);
}
nsCOMPtr<nsISupportsPRInt32> width;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(width));
if (width) {
rv = width->SetData(childRect.width);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("width"), width);
}
nsCOMPtr<nsISupportsPRInt32> height;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(height));
if (height) {
rv = height->SetData(childRect.height);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("height"), height);
}
nsIPresState* result = state;
NS_ADDREF(result);
return result;
}
void
nsGfxScrollFrameInner::RestoreState(nsIPresState* aState)
{
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsCOMPtr<nsISupportsPRInt32> width;
nsCOMPtr<nsISupportsPRInt32> height;
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), getter_AddRefs(xoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), getter_AddRefs(yoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("width"), getter_AddRefs(width));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("height"), getter_AddRefs(height));
if (xoffset && yoffset) {
PRInt32 x,y,w,h;
nsresult rv = xoffset->GetData(&x);
if (NS_SUCCEEDED(rv))
rv = yoffset->GetData(&y);
if (NS_SUCCEEDED(rv))
rv = width->GetData(&w);
if (NS_SUCCEEDED(rv))
rv = height->GetData(&h);
mLastPos.x = -1;
mLastPos.y = -1;
mRestoreRect.SetRect(-1, -1, -1, -1);
// don't do it now, store it later and do it in layout.
if (NS_SUCCEEDED(rv)) {
mRestoreRect.SetRect(x, y, w, h);
nsIScrollableView* scrollingView = GetScrollableView();
if (scrollingView) {
scrollingView->GetScrollPosition(mLastPos.x, mLastPos.y);
mDidHistoryRestore = PR_TRUE;
}
}
}
}

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

@ -42,6 +42,8 @@
#include "nsBoxFrame.h"
#include "nsIScrollableFrame.h"
#include "nsIScrollPositionListener.h"
#include "nsIPresState.h"
#include "nsIStatefulFrame.h"
class nsISupportsArray;
class nsIScrollableView;
@ -110,6 +112,9 @@ public:
void ScrollToRestoredPosition();
already_AddRefed<nsIPresState> SaveState();
void RestoreState(nsIPresState* aState);
nsIFrame* GetScrolledFrame() const {
nsIBox* childBox;
nsIFrame* frame;
@ -136,6 +141,9 @@ public:
nsBoxFrame* mOuter;
nscoord mMaxElementWidth;
nsRect mRestoreRect;
nsPoint mLastPos;
// The last dir value we saw in AddHorizontalScrollbar. Use PRInt16
// so we can fit all the possible values of a PRUint8 and have a -1
// value that indicates "not set")
@ -146,11 +154,9 @@ public:
PRPackedBool mHasVerticalScrollbar;
PRPackedBool mHasHorizontalScrollbar;
PRPackedBool mFirstPass;
PRPackedBool mIsRoot;
PRPackedBool mNeverReflowed;
PRPackedBool mViewInitiatedScroll;
PRPackedBool mFrameInitiatedScroll;
PRPackedBool mDidHistoryRestore;
};
/**
@ -164,7 +170,8 @@ public:
*/
class nsHTMLScrollFrame : public nsBoxFrame,
public nsIScrollableFrame,
public nsIAnonymousContentCreator {
public nsIAnonymousContentCreator,
public nsIStatefulFrame {
public:
friend nsresult NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
PRBool aIsRoot);
@ -248,6 +255,18 @@ public:
virtual void CurPosAttributeChanged(nsIContent* aChild, PRInt32 aModType);
// nsIStatefulFrame
NS_IMETHOD SaveState(nsPresContext* aPresContext, nsIPresState** aState) {
NS_ENSURE_ARG_POINTER(aState);
*aState = mInner.SaveState().get();
return NS_OK;
}
NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsIPresState* aState) {
NS_ENSURE_ARG_POINTER(aState);
mInner.RestoreState(aState);
return NS_OK;
}
virtual void ScrollToRestoredPosition() {
mInner.ScrollToRestoredPosition();
}
@ -269,6 +288,8 @@ public:
virtual nsresult GetContentOf(nsIContent** aContent);
PRBool DidHistoryRestore() { return mInner.mDidHistoryRestore; }
#ifdef ACCESSIBILITY
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
#endif
@ -293,7 +314,8 @@ private:
*/
class nsXULScrollFrame : public nsBoxFrame,
public nsIScrollableFrame,
public nsIAnonymousContentCreator {
public nsIAnonymousContentCreator,
public nsIStatefulFrame {
public:
friend nsresult NS_NewXULScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
PRBool aIsRoot);
@ -377,6 +399,18 @@ public:
virtual void CurPosAttributeChanged(nsIContent* aChild, PRInt32 aModType);
// nsIStatefulFrame
NS_IMETHOD SaveState(nsPresContext* aPresContext, nsIPresState** aState) {
NS_ENSURE_ARG_POINTER(aState);
*aState = mInner.SaveState().get();
return NS_OK;
}
NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsIPresState* aState) {
NS_ENSURE_ARG_POINTER(aState);
mInner.RestoreState(aState);
return NS_OK;
}
virtual void ScrollToRestoredPosition() {
mInner.ScrollToRestoredPosition();
}

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

@ -70,6 +70,7 @@
#include "nsIURI.h"
#include "nsGUIEvent.h"
#include "nsContentCreatorFunctions.h"
#include "nsISupportsPrimitives.h"
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#endif
@ -606,6 +607,7 @@ NS_INTERFACE_MAP_BEGIN(nsHTMLScrollFrame)
#endif
NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame)
NS_INTERFACE_MAP_ENTRY(nsIScrollableViewProvider)
NS_INTERFACE_MAP_ENTRY(nsIStatefulFrame)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
//----------nsXULScrollFrame-------------------------------------------
@ -1119,6 +1121,7 @@ NS_INTERFACE_MAP_BEGIN(nsXULScrollFrame)
#endif
NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame)
NS_INTERFACE_MAP_ENTRY(nsIScrollableViewProvider)
NS_INTERFACE_MAP_ENTRY(nsIStatefulFrame)
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
@ -1133,16 +1136,16 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsBoxFrame* aOuter)
mOnePixel(20),
mOuter(aOuter),
mMaxElementWidth(0),
mRestoreRect(-1, -1, -1, -1),
mLastPos(-1, -1),
mLastDir(-1),
mNeverHasVerticalScrollbar(PR_FALSE),
mNeverHasHorizontalScrollbar(PR_FALSE),
mHasVerticalScrollbar(PR_FALSE),
mHasHorizontalScrollbar(PR_FALSE),
mFirstPass(PR_FALSE),
mIsRoot(PR_FALSE),
mNeverReflowed(PR_TRUE),
mViewInitiatedScroll(PR_FALSE),
mFrameInitiatedScroll(PR_FALSE)
mFrameInitiatedScroll(PR_FALSE),
mDidHistoryRestore(PR_FALSE)
{
}
@ -1208,10 +1211,65 @@ nsGfxScrollFrameInner::GetScrollbarStylesFromFrame() const
return result;
}
/**
* this code is resposible for restoring the scroll position back to some
* saved positon. if the user has not moved the scroll position manually
* we keep scrolling down until we get to our orignally position. keep in
* mind that content could incrementally be coming in. we only want to stop
* when we reach our new position.
*/
void
nsGfxScrollFrameInner::ScrollToRestoredPosition()
{
NS_STATIC_CAST(nsScrollBoxFrame*, mScrollAreaBox)->ScrollToRestoredPosition();
nsIScrollableView* scrollingView = GetScrollableView();
if (!scrollingView) {
return;
}
if (mRestoreRect.y == -1 || mLastPos.x == -1 || mLastPos.y == -1) {
return;
}
// make sure our scroll position did not change for where we last put
// it. if it does then the user must have moved it, and we no longer
// need to restore.
nscoord x = 0;
nscoord y = 0;
scrollingView->GetScrollPosition(x, y);
// if we didn't move, we still need to restore
if (x == mLastPos.x && y == mLastPos.y) {
nsRect childRect(0, 0, 0, 0);
nsIView* child = nsnull;
nsresult rv = scrollingView->GetScrolledView(child);
if (NS_SUCCEEDED(rv) && child)
childRect = child->GetBounds();
PRInt32 cx, cy, x, y;
scrollingView->GetScrollPosition(cx,cy);
x = (int)
(((float)childRect.width / mRestoreRect.width) * mRestoreRect.x);
y = (int)
(((float)childRect.height / mRestoreRect.height) * mRestoreRect.y);
// if our position is greater than the scroll position, scroll.
// remember that we could be incrementally loading so we may enter
// and scroll many times.
if (y > cy || x > cx) {
scrollingView->ScrollTo(x, y, 0);
// scrollpostion goes from twips to pixels. this fixes any roundoff
// problems.
scrollingView->GetScrollPosition(mLastPos.x, mLastPos.y);
} else {
// if we reached the position then stop
mRestoreRect.y = -1;
mLastPos.x = -1;
mLastPos.y = -1;
}
} else {
// user moved the position, so we won't need to restore
mLastPos.x = -1;
mLastPos.y = -1;
}
}
void
@ -2032,6 +2090,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
}
}
ScrollToRestoredPosition();
return NS_OK;
}
@ -2135,3 +2195,111 @@ nsGfxScrollFrameInner::GetIntegerAttribute(nsIBox* aBox, nsIAtom* atom, PRInt32
return defaultValue;
}
already_AddRefed<nsIPresState>
nsGfxScrollFrameInner::SaveState()
{
nsCOMPtr<nsIScrollbarMediator> mediator;
nsIFrame* first = GetScrolledFrame();
mediator = do_QueryInterface(first);
if (mediator) {
// Child manages its own scrolling. Bail.
return nsnull;
}
nsIScrollableView* scrollingView = GetScrollableView();
PRInt32 x,y;
scrollingView->GetScrollPosition(x,y);
// Don't save scroll position if we are at (0,0)
if (!x && !y) {
return nsnull;
}
nsIView* child = nsnull;
scrollingView->GetScrolledView(child);
if (!child) {
return nsnull;
}
nsRect childRect = child->GetBounds();
nsCOMPtr<nsIPresState> state;
nsresult rv = NS_NewPresState(getter_AddRefs(state));
NS_ENSURE_SUCCESS(rv, nsnull);
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(xoffset));
if (xoffset) {
rv = xoffset->SetData(x);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), xoffset);
}
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(yoffset));
if (yoffset) {
rv = yoffset->SetData(y);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), yoffset);
}
nsCOMPtr<nsISupportsPRInt32> width;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(width));
if (width) {
rv = width->SetData(childRect.width);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("width"), width);
}
nsCOMPtr<nsISupportsPRInt32> height;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(height));
if (height) {
rv = height->SetData(childRect.height);
NS_ENSURE_SUCCESS(rv, nsnull);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("height"), height);
}
nsIPresState* result = state;
NS_ADDREF(result);
return result;
}
void
nsGfxScrollFrameInner::RestoreState(nsIPresState* aState)
{
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsCOMPtr<nsISupportsPRInt32> width;
nsCOMPtr<nsISupportsPRInt32> height;
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), getter_AddRefs(xoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), getter_AddRefs(yoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("width"), getter_AddRefs(width));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("height"), getter_AddRefs(height));
if (xoffset && yoffset) {
PRInt32 x,y,w,h;
nsresult rv = xoffset->GetData(&x);
if (NS_SUCCEEDED(rv))
rv = yoffset->GetData(&y);
if (NS_SUCCEEDED(rv))
rv = width->GetData(&w);
if (NS_SUCCEEDED(rv))
rv = height->GetData(&h);
mLastPos.x = -1;
mLastPos.y = -1;
mRestoreRect.SetRect(-1, -1, -1, -1);
// don't do it now, store it later and do it in layout.
if (NS_SUCCEEDED(rv)) {
mRestoreRect.SetRect(x, y, w, h);
nsIScrollableView* scrollingView = GetScrollableView();
if (scrollingView) {
scrollingView->GetScrollPosition(mLastPos.x, mLastPos.y);
mDidHistoryRestore = PR_TRUE;
}
}
}
}

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

@ -42,6 +42,8 @@
#include "nsBoxFrame.h"
#include "nsIScrollableFrame.h"
#include "nsIScrollPositionListener.h"
#include "nsIPresState.h"
#include "nsIStatefulFrame.h"
class nsISupportsArray;
class nsIScrollableView;
@ -110,6 +112,9 @@ public:
void ScrollToRestoredPosition();
already_AddRefed<nsIPresState> SaveState();
void RestoreState(nsIPresState* aState);
nsIFrame* GetScrolledFrame() const {
nsIBox* childBox;
nsIFrame* frame;
@ -136,6 +141,9 @@ public:
nsBoxFrame* mOuter;
nscoord mMaxElementWidth;
nsRect mRestoreRect;
nsPoint mLastPos;
// The last dir value we saw in AddHorizontalScrollbar. Use PRInt16
// so we can fit all the possible values of a PRUint8 and have a -1
// value that indicates "not set")
@ -146,11 +154,9 @@ public:
PRPackedBool mHasVerticalScrollbar;
PRPackedBool mHasHorizontalScrollbar;
PRPackedBool mFirstPass;
PRPackedBool mIsRoot;
PRPackedBool mNeverReflowed;
PRPackedBool mViewInitiatedScroll;
PRPackedBool mFrameInitiatedScroll;
PRPackedBool mDidHistoryRestore;
};
/**
@ -164,7 +170,8 @@ public:
*/
class nsHTMLScrollFrame : public nsBoxFrame,
public nsIScrollableFrame,
public nsIAnonymousContentCreator {
public nsIAnonymousContentCreator,
public nsIStatefulFrame {
public:
friend nsresult NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
PRBool aIsRoot);
@ -248,6 +255,18 @@ public:
virtual void CurPosAttributeChanged(nsIContent* aChild, PRInt32 aModType);
// nsIStatefulFrame
NS_IMETHOD SaveState(nsPresContext* aPresContext, nsIPresState** aState) {
NS_ENSURE_ARG_POINTER(aState);
*aState = mInner.SaveState().get();
return NS_OK;
}
NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsIPresState* aState) {
NS_ENSURE_ARG_POINTER(aState);
mInner.RestoreState(aState);
return NS_OK;
}
virtual void ScrollToRestoredPosition() {
mInner.ScrollToRestoredPosition();
}
@ -269,6 +288,8 @@ public:
virtual nsresult GetContentOf(nsIContent** aContent);
PRBool DidHistoryRestore() { return mInner.mDidHistoryRestore; }
#ifdef ACCESSIBILITY
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
#endif
@ -293,7 +314,8 @@ private:
*/
class nsXULScrollFrame : public nsBoxFrame,
public nsIScrollableFrame,
public nsIAnonymousContentCreator {
public nsIAnonymousContentCreator,
public nsIStatefulFrame {
public:
friend nsresult NS_NewXULScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
PRBool aIsRoot);
@ -377,6 +399,18 @@ public:
virtual void CurPosAttributeChanged(nsIContent* aChild, PRInt32 aModType);
// nsIStatefulFrame
NS_IMETHOD SaveState(nsPresContext* aPresContext, nsIPresState** aState) {
NS_ENSURE_ARG_POINTER(aState);
*aState = mInner.SaveState().get();
return NS_OK;
}
NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsIPresState* aState) {
NS_ENSURE_ARG_POINTER(aState);
mInner.RestoreState(aState);
return NS_OK;
}
virtual void ScrollToRestoredPosition() {
mInner.ScrollToRestoredPosition();
}

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

@ -3511,14 +3511,8 @@ PresShell::EndLoad(nsIDocument *aDocument)
CallQueryInterface(scrollFrame, &scrollableFrame);
NS_ASSERTION(scrollableFrame, "RootScrollFrame is not scrollable?");
if (scrollableFrame) {
// XXX We shouldn't depend on the scrolling guts here. Make this
// go away!
nsIFrame* scrollBoxFrame = scrollFrame->GetFirstChild(nsnull);
if (scrollBoxFrame) {
FrameManager()->RestoreFrameStateFor(scrollBoxFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
}
FrameManager()->RestoreFrameStateFor(scrollFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
scrollableFrame->ScrollToRestoredPosition();
}
}
@ -4503,13 +4497,8 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
if (aLeavingPage) {
nsIFrame* scrollFrame = GetRootScrollFrame(rootFrame);
if (scrollFrame) {
// XXX We shouldn't depend on the scrolling guts here. Make this
// go away!
nsIFrame* scrollBoxFrame = scrollFrame->GetFirstChild(nsnull);
if (scrollBoxFrame) {
FrameManager()->CaptureFrameStateFor(scrollBoxFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
}
FrameManager()->CaptureFrameStateFor(scrollFrame, historyState,
nsIStatefulFrame::eDocumentScrollState);
}
}

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

@ -294,6 +294,7 @@ nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
mIsAllFramesHere = PR_FALSE;
mHasBeenInitialized = PR_FALSE;
mNeedToReset = PR_TRUE;
mPostChildrenLoadedReset = PR_FALSE;
mCacheSize.width = -1;
mCacheSize.height = -1;
@ -558,129 +559,9 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
*aInstancePtr = (void *)((nsISelectControlFrame*)this);
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) {
*aInstancePtr =
NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIStatefulFrame*,this));
return NS_OK;
}
return nsHTMLScrollFrame::QueryInterface(aIID, aInstancePtr);
}
//----------------------------------------------------------------------
// nsIStatefulFrame
// These methods were originally in the nsScrollFrame superclass,
// but were moved here when nsListControlFrame switched to use
// nsHTMLScrollFrame.
//----------------------------------------------------------------------
NS_IMETHODIMP
nsListControlFrame::SaveState(nsPresContext* aPresContext,
nsIPresState** aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsCOMPtr<nsIPresState> state;
nsresult res = NS_OK;
nsIScrollableView* scrollingView = GetScrollableView();
nscoord x = 0, y = 0;
if (scrollingView) {
scrollingView->GetScrollPosition(x, y);
}
// Don't save scroll position if we are at (0,0)
if (x || y) {
nsIView* child = nsnull;
scrollingView->GetScrolledView(child);
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
nsRect childRect = child->GetBounds();
res = NS_NewPresState(getter_AddRefs(state));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsISupportsPRInt32> xoffset =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (xoffset) {
res = xoffset->SetData(x);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), xoffset);
}
nsCOMPtr<nsISupportsPRInt32> yoffset =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (yoffset) {
res = yoffset->SetData(y);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), yoffset);
}
nsCOMPtr<nsISupportsPRInt32> width =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (width) {
res = width->SetData(childRect.width);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("width"), width);
}
nsCOMPtr<nsISupportsPRInt32> height =
do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res);
if (height) {
res = height->SetData(childRect.height);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("height"), height);
}
*aState = state;
NS_ADDREF(*aState);
}
return res;
}
//-----------------------------------------------------------
NS_IMETHODIMP
nsListControlFrame::RestoreState(nsPresContext* aPresContext,
nsIPresState* aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsCOMPtr<nsISupportsPRInt32> width;
nsCOMPtr<nsISupportsPRInt32> height;
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), getter_AddRefs(xoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), getter_AddRefs(yoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("width"), getter_AddRefs(width));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("height"), getter_AddRefs(height));
nsresult res = NS_ERROR_NULL_POINTER;
if (xoffset && yoffset) {
PRInt32 x,y,w,h;
res = xoffset->GetData(&x);
if (NS_SUCCEEDED(res))
res = yoffset->GetData(&y);
if (NS_SUCCEEDED(res))
res = width->GetData(&w);
if (NS_SUCCEEDED(res))
res = height->GetData(&h);
if (NS_SUCCEEDED(res)) {
nsIScrollableView* scrollingView = GetScrollableView();
if (scrollingView) {
nsIView* child = nsnull;
nsRect childRect(0,0,0,0);
if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) {
childRect = child->GetBounds();
}
x = (int)(((float)childRect.width / w) * x);
y = (int)(((float)childRect.height / h) * y);
scrollingView->ScrollTo(x,y,0);
}
}
}
return res;
}
#ifdef ACCESSIBILITY
NS_IMETHODIMP nsListControlFrame::GetAccessible(nsIAccessible** aAccessible)
{
@ -1885,7 +1766,7 @@ nsListControlFrame::MouseClicked(nsPresContext* aPresContext)
NS_IMETHODIMP
nsListControlFrame::OnContentReset()
{
ResetList();
ResetList(PR_TRUE);
return NS_OK;
}
@ -1894,7 +1775,7 @@ nsListControlFrame::OnContentReset()
// those values as determined by the original HTML
//---------------------------------------------------------
void
nsListControlFrame::ResetList()
nsListControlFrame::ResetList(PRBool aAllowScrolling)
{
REFLOW_DEBUG_MSG("LBX::ResetList\n");
@ -1904,14 +1785,18 @@ nsListControlFrame::ResetList()
return;
}
// Scroll to the selected index
PRInt32 indexToSelect = kNothingSelected;
if (aAllowScrolling) {
mPostChildrenLoadedReset = PR_TRUE;
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(mContent));
NS_ASSERTION(selectElement, "No select element!");
if (selectElement) {
selectElement->GetSelectedIndex(&indexToSelect);
ScrollToIndex(indexToSelect);
// Scroll to the selected index
PRInt32 indexToSelect = kNothingSelected;
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(mContent));
NS_ASSERTION(selectElement, "No select element!");
if (selectElement) {
selectElement->GetSelectedIndex(&indexToSelect);
ScrollToIndex(indexToSelect);
}
}
mStartSelectionIndex = kNothingSelected;
@ -2095,7 +1980,7 @@ nsListControlFrame::DoneAddingChildren(PRBool aIsDone)
// if all the frames are now present we can initalize
if (CheckIfAllFramesHere()) {
mHasBeenInitialized = PR_TRUE;
ResetList();
ResetList(PR_TRUE);
}
}
}
@ -2129,6 +2014,7 @@ nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
// Make sure we scroll to the selected option as needed
mNeedToReset = PR_TRUE;
mPostChildrenLoadedReset = mIsAllContentHere;
return NS_OK;
}
@ -2139,6 +2025,7 @@ nsListControlFrame::RemoveOption(nsPresContext* aPresContext, PRInt32 aIndex)
// Need to reset if we're a dropdown
if (IsInDropDownMode()) {
mNeedToReset = PR_TRUE;
mPostChildrenLoadedReset = mIsAllContentHere;
}
return NS_OK;
@ -2444,7 +2331,16 @@ nsListControlFrame::DidReflow(nsPresContext* aPresContext,
if (mNeedToReset) {
mNeedToReset = PR_FALSE;
ResetList();
// Suppress scrolling to the selected element if we restored
// scroll history state AND the list contents have not changed
// since we loaded all the children AND nothing else forced us
// to scroll by calling ResetList(PR_TRUE). The latter two conditions
// are folded into mPostChildrenLoadedReset.
//
// The idea is that we want scroll history restoration to trump ResetList
// scrolling to the selected element, when the ResetList was probably only
// caused by content loading normally.
ResetList(!DidHistoryRestore() || mPostChildrenLoadedReset);
}
return rv;
@ -2841,6 +2737,8 @@ nsresult
nsListControlFrame::ScrollToIndex(PRInt32 aIndex)
{
if (aIndex < 0) {
// XXX shouldn't we just do nothing if we're asked to scroll to
// kNothingSelected?
return ScrollToFrame(nsnull);
} else {
nsCOMPtr<nsIContent> content = getter_AddRefs(GetOptionContent(aIndex));

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

@ -52,7 +52,6 @@
#include "nsIFormControlFrame.h"
#include "nsIListControlFrame.h"
#include "nsISelectControlFrame.h"
#include "nsIStatefulFrame.h"
#include "nsIDOMEventListener.h"
#include "nsIPresState.h"
#include "nsIContent.h"
@ -77,7 +76,6 @@ class nsListEventListener;
class nsListControlFrame : public nsHTMLScrollFrame,
public nsIFormControlFrame,
public nsIListControlFrame,
public nsIStatefulFrame,
public nsISelectControlFrame
{
public:
@ -190,10 +188,6 @@ public:
NS_IMETHOD GetDummyFrame(nsIFrame** aFrame);
NS_IMETHOD SetDummyFrame(nsIFrame* aFrame);
//nsIStatefulFrame
NS_IMETHOD SaveState(nsPresContext* aPresContext, nsIPresState** aState);
NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsIPresState* aState);
// mouse event listeners
nsresult MouseDown(nsIDOMEvent* aMouseEvent);
nsresult MouseUp(nsIDOMEvent* aMouseEvent);
@ -231,7 +225,7 @@ protected:
PRBool IsClickingInCombobox(nsIDOMEvent* aMouseEvent);
void AdjustIndexForDisabledOpt(PRInt32 aStartIndex, PRInt32 &anNewIndex,
PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext);
virtual void ResetList();
virtual void ResetList(PRBool aAllowScrolling);
nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument);
virtual ~nsListControlFrame();
@ -282,6 +276,7 @@ protected:
PRPackedBool mIsAllFramesHere;
PRPackedBool mHasBeenInitialized;
PRPackedBool mNeedToReset;
PRPackedBool mPostChildrenLoadedReset;
PRPackedBool mOverrideReflowOpt;

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

@ -84,9 +84,7 @@ NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
return NS_OK;
}
nsScrollBoxFrame::nsScrollBoxFrame(nsIPresShell* aShell):nsBoxFrame(aShell), mVerticalOverflow(PR_FALSE), mHorizontalOverflow(PR_FALSE),
mRestoreRect(-1, -1, -1, -1),
mLastPos(-1, -1)
nsScrollBoxFrame::nsScrollBoxFrame(nsIPresShell* aShell):nsBoxFrame(aShell), mVerticalOverflow(PR_FALSE), mHorizontalOverflow(PR_FALSE)
{
}
@ -438,76 +436,9 @@ nsScrollBoxFrame::DoLayout(nsBoxLayoutState& aState)
PostScrollPortEvent(shell, mHorizontalOverflow, nsScrollPortEvent::horizontal);
}
ScrollToRestoredPosition();
return NS_OK;
}
/**
* this code is resposible for restoring the scroll position back to some
* saved positon. if the user has not moved the scroll position manually
* we keep scrolling down until we get to our orignally position. keep in
* mind that content could incrementally be coming in. we only want to stop
* when we reach our new position.
*/
void
nsScrollBoxFrame::ScrollToRestoredPosition()
{
nsIView* view = GetView();
NS_ASSERTION(view, "Scrollbox must always have a view!");
if (view && mRestoreRect.y != -1 && mLastPos.x != -1 && mLastPos.y != -1) {
// make sure our scroll position did not change for where we last put
// it. if it does then the user must have moved it, and we no longer
// need to restore.
nsIScrollableView* scrollingView;
CallQueryInterface(view, &scrollingView);
if (scrollingView) {
nscoord x = 0;
nscoord y = 0;
scrollingView->GetScrollPosition(x, y);
// if we didn't move, we still need to restore
if ((x == mLastPos.x) && (y == mLastPos.y)) {
nsRect childRect(0, 0, 0, 0);
nsIView* child = nsnull;
nsresult rv = scrollingView->GetScrolledView(child);
if (NS_SUCCEEDED(rv) && child)
childRect = child->GetBounds();
PRInt32 cx, cy, x, y;
scrollingView->GetScrollPosition(cx,cy);
x = (int)
(((float)childRect.width / mRestoreRect.width) * mRestoreRect.x);
y = (int)
(((float)childRect.height / mRestoreRect.height) * mRestoreRect.y);
// if our position is greater than the scroll position, scroll.
// remember that we could be incrementally loading so we may enter
// and scroll many times.
if ((y > cy) || (x > cx)) {
scrollingView->ScrollTo(x, y, 0);
// scrollpostion goes from twips to pixels. this fixes any roundoff
// problems.
scrollingView->GetScrollPosition(mLastPos.x, mLastPos.y);
}
else {
// if we reached the position then stop
mRestoreRect.y = -1;
mLastPos.x = -1;
mLastPos.y = -1;
}
}
else {
// user moved the position, so we won't need to restore
mLastPos.x = -1;
mLastPos.y = -1;
}
}
}
}
void
nsScrollBoxFrame::PostScrollPortEvent(nsIPresShell* aShell, PRBool aOverflow, nsScrollPortEvent::orientType aType)
{
@ -638,140 +569,9 @@ nsScrollBoxFrame::Release(void)
return NS_OK;
}
//----------------------------------------------------------------------
// nsIStatefulFrame
//----------------------------------------------------------------------
NS_IMETHODIMP
nsScrollBoxFrame::SaveState(nsPresContext* aPresContext,
nsIPresState** aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsCOMPtr<nsIScrollbarMediator> mediator;
nsIFrame* first = mFrames.FirstChild();
mediator = do_QueryInterface(first);
if (mediator) {
// Child manages its own scrolling. Bail.
return NS_OK;
}
nsCOMPtr<nsIPresState> state;
nsresult res = NS_OK;
nsIView* view = GetView();
NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
PRInt32 x,y;
nsIScrollableView* scrollingView;
res = CallQueryInterface(view, &scrollingView);
NS_ENSURE_SUCCESS(res, res);
scrollingView->GetScrollPosition(x,y);
// Don't save scroll position if we are at (0,0)
if (x || y) {
nsIView* child = nsnull;
scrollingView->GetScrolledView(child);
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
nsRect childRect = child->GetBounds();
res = NS_NewPresState(getter_AddRefs(state));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(xoffset));
if (xoffset) {
res = xoffset->SetData(x);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), xoffset);
}
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(yoffset));
if (yoffset) {
res = yoffset->SetData(y);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), yoffset);
}
nsCOMPtr<nsISupportsPRInt32> width;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(width));
if (width) {
res = width->SetData(childRect.width);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("width"), width);
}
nsCOMPtr<nsISupportsPRInt32> height;
nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID,
nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(height));
if (height) {
res = height->SetData(childRect.height);
NS_ENSURE_SUCCESS(res, res);
state->SetStatePropertyAsSupports(NS_LITERAL_STRING("height"), height);
}
*aState = state;
NS_ADDREF(*aState);
}
return res;
}
//-----------------------------------------------------------
NS_IMETHODIMP
nsScrollBoxFrame::RestoreState(nsPresContext* aPresContext,
nsIPresState* aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsCOMPtr<nsISupportsPRInt32> xoffset;
nsCOMPtr<nsISupportsPRInt32> yoffset;
nsCOMPtr<nsISupportsPRInt32> width;
nsCOMPtr<nsISupportsPRInt32> height;
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), getter_AddRefs(xoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), getter_AddRefs(yoffset));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("width"), getter_AddRefs(width));
aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("height"), getter_AddRefs(height));
nsresult res = NS_ERROR_NULL_POINTER;
if (xoffset && yoffset) {
PRInt32 x,y,w,h;
res = xoffset->GetData(&x);
if (NS_SUCCEEDED(res))
res = yoffset->GetData(&y);
if (NS_SUCCEEDED(res))
res = width->GetData(&w);
if (NS_SUCCEEDED(res))
res = height->GetData(&h);
mLastPos.x = -1;
mLastPos.y = -1;
mRestoreRect.SetRect(-1, -1, -1, -1);
// don't do it now, store it later and do it in layout.
if (NS_SUCCEEDED(res)) {
mRestoreRect.SetRect(x, y, w, h);
nsIView* view = GetView();
if (!view)
return NS_ERROR_FAILURE;
nsIScrollableView* scrollingView;
CallQueryInterface(view, &scrollingView);
if (scrollingView)
scrollingView->GetScrollPosition(mLastPos.x, mLastPos.y);
}
}
return res;
}
NS_INTERFACE_MAP_BEGIN(nsScrollBoxFrame)
NS_INTERFACE_MAP_ENTRY(nsIBox)
NS_INTERFACE_MAP_ENTRY(nsIStatefulFrame)
#ifdef NS_DEBUG
NS_INTERFACE_MAP_ENTRY(nsIFrameDebug)
#endif

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

@ -50,7 +50,7 @@
* Scroll frames don't support incremental changes, i.e. you can't replace
* or remove the scrolled frame
*/
class nsScrollBoxFrame : public nsBoxFrame, public nsIStatefulFrame {
class nsScrollBoxFrame : public nsBoxFrame {
public:
friend nsresult NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
@ -124,8 +124,6 @@ public:
virtual nsIView* GetMouseCapturer() const;
void ScrollToRestoredPosition();
protected:
nsScrollBoxFrame(nsIPresShell* aShell);
@ -137,17 +135,11 @@ protected:
nsIFrame* aParent,
nsIView** aParentView);
//nsIStatefulFrame
NS_IMETHOD SaveState(nsPresContext* aPresContext, nsIPresState** aState);
NS_IMETHOD RestoreState(nsPresContext* aPresContext, nsIPresState* aState);
private:
nsresult CreateScrollingView(nsPresContext* aPresContext);
PRPackedBool mVerticalOverflow;
PRPackedBool mHorizontalOverflow;
nsRect mRestoreRect;
nsPoint mLastPos;
protected:
virtual PRBool NeedsClipWidget();
virtual void PostScrollPortEvent(nsIPresShell* aShell, PRBool aOverflow, nsScrollPortEvent::orientType aType);