From 73d33434d9194ed2fd660cd1e3dc0fafdf851887 Mon Sep 17 00:00:00 2001 From: "dbaron%fas.harvard.edu" Date: Wed, 10 Jan 2001 02:43:00 +0000 Subject: [PATCH] Change ScrollFrameIntoView so that scrolling to an inline frame scrolls to the top of the line containing the inline frame rather than the frame itself. This makes scrolling to empty inline anchors or anchors around images work better. b=38280 r=buster@netscape.com sr=waterson@netscape.com git-svn-id: svn://10.0.0.236/trunk@84693 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsPresShell.cpp | 39 ++++++++++++++++++++ mozilla/layout/html/base/src/nsPresShell.cpp | 39 ++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 6b12c92ec28..58c2abeb3b6 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -93,6 +93,7 @@ #include "nsILayoutHistoryState.h" #include "nsIScrollPositionListener.h" #include "nsICompositeListener.h" +#include "nsILineIterator.h" // for ScrollFrameIntoView #include "nsTimer.h" #include "nsWeakPtr.h" #include "plarena.h" @@ -3418,6 +3419,44 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame, scrollingView->GetScrolledView(scrolledView); aFrame->GetOffsetFromView(mPresContext, offset, &closestView); + // If this is an inline frame, we need to change the top of the + // offset to include the whole line. + nsCOMPtr frameType; + nsIFrame *prevFrame = aFrame; + nsIFrame *frame = aFrame; + while (frame && (frame->GetFrameType(getter_AddRefs(frameType)), + frameType.get() == nsLayoutAtoms::inlineFrame)) { + prevFrame = frame; + prevFrame->GetParent(&frame); + } + if (frame != aFrame && + frame && + frameType.get() == nsLayoutAtoms::blockFrame) { + // find the line containing aFrame and increase the top of |offset|. + nsCOMPtr lines( do_QueryInterface(frame) ); + if (lines) { + PRInt32 index = -1; + lines->FindLineContaining(prevFrame, &index); + if (index >= 0) { + nsIFrame *trash1; + PRInt32 trash2; + nsRect lineBounds; + PRUint32 trash3; + if (NS_SUCCEEDED(lines->GetLine(index, &trash1, &trash2, + lineBounds, &trash3))) { + nsPoint blockOffset; + nsIView* blockView; + frame->GetOffsetFromView(mPresContext, blockOffset, &blockView); + if (blockView == closestView) { + // XXX If views not equal, this is hard. Do we want to bother? + nscoord newoffset = lineBounds.y + blockOffset.y; + if (newoffset < offset.y) offset.y = newoffset; + } + } + } + } + } + // XXX Deal with the case where there is a scrolled element, e.g., a // DIV in the middle... while ((closestView != nsnull) && (closestView != scrolledView)) { diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 6b12c92ec28..58c2abeb3b6 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -93,6 +93,7 @@ #include "nsILayoutHistoryState.h" #include "nsIScrollPositionListener.h" #include "nsICompositeListener.h" +#include "nsILineIterator.h" // for ScrollFrameIntoView #include "nsTimer.h" #include "nsWeakPtr.h" #include "plarena.h" @@ -3418,6 +3419,44 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame, scrollingView->GetScrolledView(scrolledView); aFrame->GetOffsetFromView(mPresContext, offset, &closestView); + // If this is an inline frame, we need to change the top of the + // offset to include the whole line. + nsCOMPtr frameType; + nsIFrame *prevFrame = aFrame; + nsIFrame *frame = aFrame; + while (frame && (frame->GetFrameType(getter_AddRefs(frameType)), + frameType.get() == nsLayoutAtoms::inlineFrame)) { + prevFrame = frame; + prevFrame->GetParent(&frame); + } + if (frame != aFrame && + frame && + frameType.get() == nsLayoutAtoms::blockFrame) { + // find the line containing aFrame and increase the top of |offset|. + nsCOMPtr lines( do_QueryInterface(frame) ); + if (lines) { + PRInt32 index = -1; + lines->FindLineContaining(prevFrame, &index); + if (index >= 0) { + nsIFrame *trash1; + PRInt32 trash2; + nsRect lineBounds; + PRUint32 trash3; + if (NS_SUCCEEDED(lines->GetLine(index, &trash1, &trash2, + lineBounds, &trash3))) { + nsPoint blockOffset; + nsIView* blockView; + frame->GetOffsetFromView(mPresContext, blockOffset, &blockView); + if (blockView == closestView) { + // XXX If views not equal, this is hard. Do we want to bother? + nscoord newoffset = lineBounds.y + blockOffset.y; + if (newoffset < offset.y) offset.y = newoffset; + } + } + } + } + } + // XXX Deal with the case where there is a scrolled element, e.g., a // DIV in the middle... while ((closestView != nsnull) && (closestView != scrolledView)) {