Commit 3f1d49a0 authored by pollmann%netscape.com's avatar pollmann%netscape.com
Browse files

Bug 32770: Save scroll position in session history r=nisheeth

parent 05c30d3e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3128,7 +3128,7 @@ NS_IMETHODIMP nsDocShell::UpdateCurrentSessionHistory()
         if (NS_SUCCEEDED(rv) && shell) {
 
           nsCOMPtr<nsILayoutHistoryState> layoutState;
           rv = shell->CaptureHistoryState(getter_AddRefs(layoutState));
           rv = shell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE);
           if (NS_SUCCEEDED(rv) && layoutState) {
 
             rv = entry->SetLayoutHistoryState(layoutState);
+66 −40
Original line number Diff line number Diff line
@@ -248,12 +248,22 @@ public:
  NS_IMETHOD AttributeAffectsStyle(nsIAtom *aAttribute, nsIContent *aContent,
                                   PRBool &aAffects);

  // Capture state from the entire frame heirarchy and store in aState
  NS_IMETHOD CaptureFrameState(nsIPresContext*        aPresContext,
                               nsIFrame*              aFrame,
                               nsILayoutHistoryState* aState);
  NS_IMETHOD RestoreFrameState(nsIPresContext*        aPresContext,
                               nsIFrame*              aFrame,
                               nsILayoutHistoryState* aState);
  // Add/restore state for one frame (special, global type, like scroll position)
  NS_IMETHOD CaptureFrameStateFor(nsIPresContext*     aPresContext,
                               nsIFrame*              aFrame,
                               nsILayoutHistoryState* aState,
                               nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID);
  NS_IMETHOD RestoreFrameStateFor(nsIPresContext*     aPresContext,
                               nsIFrame*              aFrame,
                               nsILayoutHistoryState* aState,
                               nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID);

  // Gets and sets properties on a given frame
  NS_IMETHOD GetFrameProperty(nsIFrame* aFrame,
@@ -1477,8 +1487,10 @@ FrameManager::AttributeAffectsStyle(nsIAtom *aAttribute, nsIContent *aContent,
  return rv;
}

static nsresult
CaptureFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState)
// Capture state for a given frame.
// Accept a content id here, in some cases we may not have content (scroll position)
NS_IMETHODIMP
FrameManager::CaptureFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID)
{
  nsresult rv = NS_OK;
  NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in");
@@ -1488,27 +1500,35 @@ CaptureFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHi
  nsIStatefulFrame* statefulFrame = nsnull;
  aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame);
  if (nsnull != statefulFrame) {
    // If so, get the content ID, state type and the state and
    // add an association between (ID, type) and (state) to the
    // history state storage object, aState.

    // If not given one, get the content ID
    PRUint32 ID = aID;
    if (nsIStatefulFrame::eNoID == ID) {
      nsCOMPtr<nsIContent> content;    
      rv = aFrame->GetContent(getter_AddRefs(content));   
    if (NS_SUCCEEDED(rv)) {
      PRUint32 ID;
      if (NS_SUCCEEDED(rv) && content) {
        rv = content->GetContentID(&ID);
      }
    }
    if (NS_SUCCEEDED(rv) && ID) { // Must have ID (don't do anonymous content)

      // Get the state type
      nsIStatefulFrame::StateType type = nsIStatefulFrame::eNoType;
      rv = statefulFrame->GetStateType(aPresContext, &type);
      if (NS_SUCCEEDED(rv)) {

        // Get the state
        nsCOMPtr<nsIPresState> frameState;
        rv = statefulFrame->SaveState(aPresContext, getter_AddRefs(frameState));
        if (NS_SUCCEEDED(rv)) {

          // add an association between (ID, type) and (state) to the
          // history state storage object, aState.
          rv = aState->AddState(ID, frameState, type);            
        }
      }
    }
  }
  }

  return rv;
}
@@ -1539,8 +1559,10 @@ FrameManager::CaptureFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame,
  return rv;
}

static nsresult
RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState)
// Restore state for a given frame.
// Accept a content id here, in some cases we may not have content (scroll position)
NS_IMETHODIMP
FrameManager::RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID)
{
  nsresult rv = NS_OK;
  NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in");
@@ -1550,20 +1572,25 @@ RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHi
  nsIStatefulFrame* statefulFrame = nsnull;
  aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame);
  if (nsnull != statefulFrame) {
    // If so, get the content ID, state type and the frame state and
    // ask the frame object to restore its state.    
    // If not given one, get the content ID
    PRUint32 ID = aID;
    if (nsIStatefulFrame::eNoID == ID) {
      nsCOMPtr<nsIContent> content;    
      rv = aFrame->GetContent(getter_AddRefs(content));   
    if (NS_SUCCEEDED(rv)) {
      PRUint32 ID;
      if (NS_SUCCEEDED(rv) && content) {
        rv = content->GetContentID(&ID);
      }
    }
    if (NS_SUCCEEDED(rv) && ID) { // Must have ID (don't do anonymous content)

      nsIStatefulFrame::StateType type = nsIStatefulFrame::eNoType;
      rv = statefulFrame->GetStateType(aPresContext, &type);
      if (NS_SUCCEEDED(rv)) {

        nsCOMPtr<nsIPresState> frameState;
        rv = aState->GetState(ID, getter_AddRefs(frameState), type);          
        if (NS_SUCCEEDED(rv) && frameState) {

          // First restore the state.
          rv = statefulFrame->RestoreState(aPresContext, frameState);

@@ -1573,7 +1600,6 @@ RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHi
      }
    }
  }  
  }  

  return rv;
}
+1 −1
Original line number Diff line number Diff line
@@ -369,7 +369,7 @@ public:
   * Get and set the history state for the current document 
   */

  NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState) = 0;
  NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage = PR_FALSE) = 0;
  NS_IMETHOD GetHistoryState(nsILayoutHistoryState** aLayoutHistoryState) = 0;
  NS_IMETHOD SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState) = 0;

+65 −2
Original line number Diff line number Diff line
@@ -642,7 +642,7 @@ public:

  NS_IMETHOD DoCopy();

  NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState);
  NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage);
  NS_IMETHOD GetHistoryState(nsILayoutHistoryState** aLayoutHistoryState);
  NS_IMETHOD SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState);

@@ -1543,6 +1543,45 @@ PresShell::NotifyReflowObservers(const char *aData)
  return NS_OK;
}

static nsresult
GetRootScrollFrame(nsIPresContext* aPresContext, nsIFrame* aRootFrame, nsIFrame** aScrollFrame) {

  // Frames: viewport->scroll->scrollport (Gfx) or viewport->scroll (Native)
  // Types:  viewport->scroll->sroll               viewport->scroll

  // Ensure root frame is a viewport frame
  *aScrollFrame = nsnull;
  nsIFrame* theFrame = nsnull;
  if (aRootFrame) {
    nsCOMPtr<nsIAtom> fType;
    aRootFrame->GetFrameType(getter_AddRefs(fType));
    if (fType && (nsLayoutAtoms::viewportFrame == fType.get())) {

      // If child is scrollframe keep it (native)
      aRootFrame->FirstChild(aPresContext, nsnull, &theFrame);
      if (theFrame) {
        nsCOMPtr<nsIAtom> fType;
        theFrame->GetFrameType(getter_AddRefs(fType));
        if (nsLayoutAtoms::scrollFrame == fType.get()) {
          *aScrollFrame = theFrame;

          // If the first child of that is scrollframe, use it instead (gfx)
          theFrame->FirstChild(aPresContext, nsnull, &theFrame);
          if (theFrame) {
            nsCOMPtr<nsIAtom> fType;
            theFrame->GetFrameType(getter_AddRefs(fType));
            if (nsLayoutAtoms::scrollFrame == fType.get()) {
              *aScrollFrame = theFrame;
            }
          }
        }
      }
    }
  }

  return NS_OK;
}

NS_IMETHODIMP
PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
{
@@ -2237,6 +2276,18 @@ PresShell::BeginLoad(nsIDocument *aDocument)
NS_IMETHODIMP
PresShell::EndLoad(nsIDocument *aDocument)
{

  // Restore frame state for the root scroll frame
  nsIFrame* rootFrame = nsnull;
  GetRootFrame(&rootFrame);
  if (rootFrame && mHistoryState) {
    nsIFrame* scrollFrame = nsnull;
    GetRootScrollFrame(mPresContext, rootFrame, &scrollFrame);
    if (scrollFrame) {
      mFrameManager->RestoreFrameStateFor(mPresContext, scrollFrame, mHistoryState, nsIStatefulFrame::eDocumentScrollState);
    }
  }

#ifdef MOZ_PERF_METRICS
  // Dump reflow, style resolution and frame construction times here.
  MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::EndLoad(), this=%p\n", this));
@@ -2814,7 +2865,7 @@ PresShell::DoCopy()
}

NS_IMETHODIMP
PresShell::CaptureHistoryState(nsILayoutHistoryState** aState)
PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPage)
{
  nsresult rv = NS_OK;

@@ -2840,6 +2891,18 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState)
  nsIFrame* rootFrame = nsnull;
  rv = GetRootFrame(&rootFrame);
  if (NS_FAILED(rv) || nsnull == rootFrame) return rv;
  // Capture frame state for the root scroll frame
  // Don't capture state when first creating doc element heirarchy
  // As the scroll position is 0 and this will cause us to loose
  // our previously saved place!
  if (aLeavingPage) {
    nsIFrame* scrollFrame = nsnull;
    rv = GetRootScrollFrame(mPresContext, rootFrame, &scrollFrame);
    if (scrollFrame) {
      rv = mFrameManager->CaptureFrameStateFor(mPresContext, scrollFrame, mHistoryState, nsIStatefulFrame::eDocumentScrollState);
    }
  }


  rv = mFrameManager->CaptureFrameState(mPresContext, rootFrame, mHistoryState);  
 
+10 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include "nslayout.h"
#include "nsISupports.h"
#include "nsIStatefulFrame.h"

class nsIAtom;
class nsIContent;
@@ -165,6 +166,15 @@ public:
  NS_IMETHOD RestoreFrameState(nsIPresContext* aPresContext,
                               nsIFrame* aFrame,
                               nsILayoutHistoryState* aState) = 0;
  // Add/restore state for one frame (special, global type, like scroll position)
  NS_IMETHOD CaptureFrameStateFor(nsIPresContext* aPresContext,
                               nsIFrame* aFrame,
                               nsILayoutHistoryState* aState,
                               nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID) = 0;
  NS_IMETHOD RestoreFrameStateFor(nsIPresContext* aPresContext,
                               nsIFrame* aFrame,
                               nsILayoutHistoryState* aState,
                               nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID) = 0;

  /**
   * Gets a property value for a given frame.
Loading