Bug 720126 - Update scroll API to use ScrollAxis parameters (where and when). r=roc

This commit is contained in:
Adam Dane [:hobophobe] 2012-03-19 21:09:50 -05:00
parent 8d0a189c1c
commit 3c986b3780
17 changed files with 388 additions and 289 deletions

View File

@ -277,9 +277,9 @@ nsAccessNode::ScrollTo(PRUint32 aScrollType)
if (!content) if (!content)
return; return;
PRInt16 vPercent, hPercent; nsIPresShell::ScrollAxis vertical, horizontal;
nsCoreUtils::ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent); nsCoreUtils::ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
shell->ScrollContentIntoView(content, vPercent, hPercent, shell->ScrollContentIntoView(content, vertical, horizontal,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
} }

View File

@ -2230,8 +2230,9 @@ nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
nsIPresShell* presShell = mDoc->PresShell(); nsIPresShell* presShell = mDoc->PresShell();
// Scroll into view. // Scroll into view.
presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE, presShell->ScrollContentIntoView(aContent,
NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(),
nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
// Fire mouse down and mouse up events. // Fire mouse down and mouse up events.

View File

@ -296,18 +296,19 @@ nsCoreUtils::ScrollSubstringTo(nsIFrame *aFrame,
nsIDOMNode *aEndNode, PRInt32 aEndIndex, nsIDOMNode *aEndNode, PRInt32 aEndIndex,
PRUint32 aScrollType) PRUint32 aScrollType)
{ {
PRInt16 vPercent, hPercent; nsIPresShell::ScrollAxis vertical, horizontal;
ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent); ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
return ScrollSubstringTo(aFrame, aStartNode, aStartIndex, aEndNode, aEndIndex, return ScrollSubstringTo(aFrame, aStartNode, aStartIndex, aEndNode, aEndIndex,
vPercent, hPercent); vertical, horizontal);
} }
nsresult nsresult
nsCoreUtils::ScrollSubstringTo(nsIFrame *aFrame, nsCoreUtils::ScrollSubstringTo(nsIFrame *aFrame,
nsIDOMNode *aStartNode, PRInt32 aStartIndex, nsIDOMNode *aStartNode, PRInt32 aStartIndex,
nsIDOMNode *aEndNode, PRInt32 aEndIndex, nsIDOMNode *aEndNode, PRInt32 aEndIndex,
PRInt16 aVPercent, PRInt16 aHPercent) nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal)
{ {
if (!aFrame || !aStartNode || !aEndNode) if (!aFrame || !aStartNode || !aEndNode)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -330,8 +331,9 @@ nsCoreUtils::ScrollSubstringTo(nsIFrame *aFrame,
selection->RemoveAllRanges(); selection->RemoveAllRanges();
selection->AddRange(scrollToRange); selection->AddRange(scrollToRange);
privSel->ScrollIntoView(nsISelectionController::SELECTION_ANCHOR_REGION, privSel->ScrollIntoViewInternal(
true, aVPercent, aHPercent); nsISelectionController::SELECTION_ANCHOR_REGION,
true, aVertical, aHorizontal);
selection->CollapseToStart(); selection->CollapseToStart();
@ -365,39 +367,57 @@ nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
void void
nsCoreUtils::ConvertScrollTypeToPercents(PRUint32 aScrollType, nsCoreUtils::ConvertScrollTypeToPercents(PRUint32 aScrollType,
PRInt16 *aVPercent, nsIPresShell::ScrollAxis *aVertical,
PRInt16 *aHPercent) nsIPresShell::ScrollAxis *aHorizontal)
{ {
PRInt16 whereY, whereX;
nsIPresShell::WhenToScroll whenY, whenX;
switch (aScrollType) switch (aScrollType)
{ {
case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT: case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT:
*aVPercent = NS_PRESSHELL_SCROLL_TOP; whereY = nsIPresShell::SCROLL_TOP;
*aHPercent = NS_PRESSHELL_SCROLL_LEFT; whenY = nsIPresShell::SCROLL_ALWAYS;
whereX = nsIPresShell::SCROLL_LEFT;
whenX = nsIPresShell::SCROLL_ALWAYS;
break; break;
case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT: case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT:
*aVPercent = NS_PRESSHELL_SCROLL_BOTTOM; whereY = nsIPresShell::SCROLL_BOTTOM;
*aHPercent = NS_PRESSHELL_SCROLL_RIGHT; whenY = nsIPresShell::SCROLL_ALWAYS;
whereX = nsIPresShell::SCROLL_RIGHT;
whenX = nsIPresShell::SCROLL_ALWAYS;
break; break;
case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE: case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE:
*aVPercent = NS_PRESSHELL_SCROLL_TOP; whereY = nsIPresShell::SCROLL_TOP;
*aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE; whenY = nsIPresShell::SCROLL_ALWAYS;
whereX = nsIPresShell::SCROLL_MINIMUM;
whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
break; break;
case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE: case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE:
*aVPercent = NS_PRESSHELL_SCROLL_BOTTOM; whereY = nsIPresShell::SCROLL_BOTTOM;
*aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE; whenY = nsIPresShell::SCROLL_ALWAYS;
whereX = nsIPresShell::SCROLL_MINIMUM;
whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
break; break;
case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE: case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE:
*aVPercent = NS_PRESSHELL_SCROLL_ANYWHERE; whereY = nsIPresShell::SCROLL_MINIMUM;
*aHPercent = NS_PRESSHELL_SCROLL_LEFT; whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
whereX = nsIPresShell::SCROLL_LEFT;
whenX = nsIPresShell::SCROLL_ALWAYS;
break; break;
case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE: case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE:
*aVPercent = NS_PRESSHELL_SCROLL_ANYWHERE; whereY = nsIPresShell::SCROLL_MINIMUM;
*aHPercent = NS_PRESSHELL_SCROLL_RIGHT; whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
whereX = nsIPresShell::SCROLL_RIGHT;
whenX = nsIPresShell::SCROLL_ALWAYS;
break; break;
default: default:
*aVPercent = NS_PRESSHELL_SCROLL_ANYWHERE; whereY = nsIPresShell::SCROLL_MINIMUM;
*aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE; whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
whereX = nsIPresShell::SCROLL_MINIMUM;
whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
} }
*aVertical = nsIPresShell::ScrollAxis(whereY, whenY);
*aHorizontal = nsIPresShell::ScrollAxis(whereX, whenX);
} }
nsIntPoint nsIntPoint

View File

@ -181,13 +181,14 @@ public:
* @param aStartOffset an offset inside the start node * @param aStartOffset an offset inside the start node
* @param aEndNode end node of a range * @param aEndNode end node of a range
* @param aEndOffset an offset inside the end node * @param aEndOffset an offset inside the end node
* @param aVPercent how to align vertically, specified in percents * @param aVertical how to align vertically, specified in percents, and when.
* @param aHPercent how to align horizontally, specified in percents * @param aHorizontal how to align horizontally, specified in percents, and when.
*/ */
static nsresult ScrollSubstringTo(nsIFrame *aFrame, static nsresult ScrollSubstringTo(nsIFrame *aFrame,
nsIDOMNode *aStartNode, PRInt32 aStartIndex, nsIDOMNode *aStartNode, PRInt32 aStartIndex,
nsIDOMNode *aEndNode, PRInt32 aEndIndex, nsIDOMNode *aEndNode, PRInt32 aEndIndex,
PRInt16 aVPercent, PRInt16 aHPercent); nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal);
/** /**
* Scrolls the given frame to the point, used for implememntation of * Scrolls the given frame to the point, used for implememntation of
@ -202,11 +203,11 @@ public:
/** /**
* Converts scroll type constant defined in nsIAccessibleScrollType to * Converts scroll type constant defined in nsIAccessibleScrollType to
* vertical and horizontal percents. * vertical and horizontal parameters.
*/ */
static void ConvertScrollTypeToPercents(PRUint32 aScrollType, static void ConvertScrollTypeToPercents(PRUint32 aScrollType,
PRInt16 *aVPercent, nsIPresShell::ScrollAxis *aVertical,
PRInt16 *aHPercent); nsIPresShell::ScrollAxis *aHorizontal);
/** /**
* Returns coordinates relative screen for the top level window. * Returns coordinates relative screen for the top level window.

View File

@ -52,6 +52,7 @@ class nsIFrame;
class nsIPresShell; class nsIPresShell;
struct nsTextRangeStyle; struct nsTextRangeStyle;
struct nsPoint; struct nsPoint;
struct ScrollAxis;
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsTArray.h" #include "nsTArray.h"
%} %}
@ -63,8 +64,9 @@ struct nsPoint;
[ref] native constTextRangeStyleRef(const nsTextRangeStyle); [ref] native constTextRangeStyleRef(const nsTextRangeStyle);
[ref] native nsPointRef(nsPoint); [ref] native nsPointRef(nsPoint);
native nsDirection(nsDirection); native nsDirection(nsDirection);
native ScrollAxis(nsIPresShell::ScrollAxis);
[scriptable, uuid(1820a940-6203-4e27-bc94-fa81131722a4)] [scriptable, uuid(0ced91b9-3e77-4191-943f-95bcde5e2d14)]
interface nsISelectionPrivate : nsISelection interface nsISelectionPrivate : nsISelection
{ {
const short ENDOFPRECEDINGLINE=0; const short ENDOFPRECEDINGLINE=0;
@ -174,29 +176,31 @@ interface nsISelectionPrivate : nsISelection
* @param aIsSynchronous - when true, scrolls the selection into view * @param aIsSynchronous - when true, scrolls the selection into view
* before returning. If false, posts a request which * before returning. If false, posts a request which
* is processed at some point after the method returns. * is processed at some point after the method returns.
* @param aVPercent - how to align the frame vertically. A value of 0 * @param aVPercent - how to align the frame vertically.
* means the frame's upper edge is aligned with the top edge * @param aHPercent - how to align the frame horizontally.
* of the visible area. A value of 100 means the frame's
* bottom edge is aligned with the bottom edge of
* the visible area. For values in between, the point
* "aVPercent" down the frame is placed at the point
* "aVPercent" down the visible area. A value of 50 centers
* the frame vertically. A value of -1 means move
* the frame the minimum amount necessary in order for
* the entire frame to be visible vertically (if possible).
* @param aHPercent - how to align the frame horizontally. A value of 0
* means the frame's left edge is aligned with the left
* edge of the visible area. A value of 100 means the
* frame's right edge is aligned with the right edge of
* the visible area. For values in between, the point
* "aHPercent" across the frame is placed at the point
* "aHPercent" across the visible area. A value of 50
* centers the frame horizontally . A value of -1 means
* move the frame the minimum amount necessary in order
* for the entire frame to be visible horizontally
* (if possible).
*/ */
void scrollIntoView(in short aRegion, in boolean aIsSynchronous, void scrollIntoView(in short aRegion, in boolean aIsSynchronous,
in short aVPercent, in short aHPercent); in PRInt16 aVPercent,
in PRInt16 aHPercent);
/**
* Scrolls a region of the selection, so that it is visible in
* the scrolled view.
*
* @param aRegion - the region inside the selection to scroll into view
* (see selection region constants defined in
* nsISelectionController).
* @param aIsSynchronous - when true, scrolls the selection into view
* before returning. If false, posts a request which
* is processed at some point after the method returns.
* @param aVertical - how to align the frame vertically and when.
* See nsIPresShell.h:ScrollAxis for details.
* @param aHorizontal - how to align the frame horizontally and when.
* See nsIPresShell.h:ScrollAxis for details.
*/
[noscript] void scrollIntoViewInternal(in short aRegion,
in boolean aIsSynchronous,
in ScrollAxis aVertical,
in ScrollAxis aHorizontal);
}; };

View File

@ -1109,8 +1109,9 @@ nsContentEventHandler::OnSelectionEvent(nsSelectionEvent* aEvent)
selPrivate->EndBatchChanges(); selPrivate->EndBatchChanges();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
selPrivate->ScrollIntoView( selPrivate->ScrollIntoViewInternal(
nsISelectionController::SELECTION_FOCUS_REGION, false, -1, -1); nsISelectionController::SELECTION_FOCUS_REGION,
false, nsIPresShell::ScrollAxis(), nsIPresShell::ScrollAxis());
aEvent->mSucceeded = true; aEvent->mSucceeded = true;
return NS_OK; return NS_OK;
} }

View File

@ -983,11 +983,14 @@ nsGenericHTMLElement::ScrollIntoView(bool aTop, PRUint8 optional_argc)
aTop = true; aTop = true;
} }
PRIntn vpercent = aTop ? NS_PRESSHELL_SCROLL_TOP : PRInt16 vpercent = aTop ? nsIPresShell::SCROLL_TOP :
NS_PRESSHELL_SCROLL_BOTTOM; nsIPresShell::SCROLL_BOTTOM;
presShell->ScrollContentIntoView(this, vpercent, presShell->ScrollContentIntoView(this,
NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(
vpercent,
nsIPresShell::SCROLL_ALWAYS),
nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK; return NS_OK;

View File

@ -1960,8 +1960,12 @@ nsFocusManager::ScrollIntoView(nsIPresShell* aPresShell,
// if the noscroll flag isn't set, scroll the newly focused element into view // if the noscroll flag isn't set, scroll the newly focused element into view
if (!(aFlags & FLAG_NOSCROLL)) if (!(aFlags & FLAG_NOSCROLL))
aPresShell->ScrollContentIntoView(aContent, aPresShell->ScrollContentIntoView(aContent,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, nsIPresShell::ScrollAxis(
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, nsIPresShell::SCROLL_MINIMUM,
nsIPresShell::SCROLL_IF_NOT_VISIBLE),
nsIPresShell::ScrollAxis(
nsIPresShell::SCROLL_MINIMUM,
nsIPresShell::SCROLL_IF_NOT_VISIBLE),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
} }

View File

@ -2705,24 +2705,27 @@ DocumentViewerImpl::GetPrintable(bool *aPrintable)
NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode) NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode)
{ {
NS_ENSURE_ARG(aNode); NS_ENSURE_ARG(aNode);
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE); NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell)), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell)), NS_ERROR_FAILURE);
// Get the nsIContent interface, because that's what we need to // Get the nsIContent interface, because that's what we need to
// get the primary frame // get the primary frame
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
// Tell the PresShell to scroll to the primary frame of the content. // Tell the PresShell to scroll to the primary frame of the content.
NS_ENSURE_SUCCESS(presShell->ScrollContentIntoView(content, NS_ENSURE_SUCCESS(
NS_PRESSHELL_SCROLL_TOP, presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(
nsIPresShell::SCROLL_OVERFLOW_HIDDEN), nsIPresShell::SCROLL_TOP,
NS_ERROR_FAILURE); nsIPresShell::SCROLL_ALWAYS),
return NS_OK; nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN),
NS_ERROR_FAILURE);
return NS_OK;
} }
void void

View File

@ -147,22 +147,13 @@ typedef struct CapturingContentInfo {
{ 0x4dc4db09, 0x03d4, 0x4427, \ { 0x4dc4db09, 0x03d4, 0x4427, \
{ 0xbe, 0xfb, 0xc9, 0x29, 0xac, 0x5c, 0x62, 0xab } } { 0xbe, 0xfb, 0xc9, 0x29, 0xac, 0x5c, 0x62, 0xab } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
#define NS_PRESSHELL_SCROLL_BOTTOM 100
#define NS_PRESSHELL_SCROLL_LEFT 0
#define NS_PRESSHELL_SCROLL_RIGHT 100
#define NS_PRESSHELL_SCROLL_CENTER 50
#define NS_PRESSHELL_SCROLL_ANYWHERE -1
#define NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE -2
// debug VerifyReflow flags // debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01 #define VERIFY_REFLOW_ON 0x01
#define VERIFY_REFLOW_NOISY 0x02 #define VERIFY_REFLOW_NOISY 0x02
#define VERIFY_REFLOW_ALL 0x04 #define VERIFY_REFLOW_ALL 0x04
#define VERIFY_REFLOW_DUMP_COMMANDS 0x08 #define VERIFY_REFLOW_DUMP_COMMANDS 0x08
#define VERIFY_REFLOW_NOISY_RC 0x10 #define VERIFY_REFLOW_NOISY_RC 0x10
#define VERIFY_REFLOW_REALLY_NOISY_RC 0x20 #define VERIFY_REFLOW_REALLY_NOISY_RC 0x20
#define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x40 #define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x40
#undef NOISY_INTERRUPTIBLE_REFLOW #undef NOISY_INTERRUPTIBLE_REFLOW
@ -533,34 +524,68 @@ public:
*/ */
virtual NS_HIDDEN_(nsresult) ScrollToAnchor() = 0; virtual NS_HIDDEN_(nsresult) ScrollToAnchor() = 0;
enum {
SCROLL_TOP = 0,
SCROLL_BOTTOM = 100,
SCROLL_LEFT = 0,
SCROLL_RIGHT = 100,
SCROLL_CENTER = 50,
SCROLL_MINIMUM = -1
};
enum WhenToScroll {
SCROLL_ALWAYS,
SCROLL_IF_NOT_VISIBLE,
SCROLL_IF_NOT_FULLY_VISIBLE
};
typedef struct ScrollAxis {
PRInt16 mWhereToScroll;
WhenToScroll mWhenToScroll;
/**
* @param aWhere: Either a percentage or a special value.
* nsIPresShell defines:
* * (Default) SCROLL_MINIMUM = -1: The visible area is
* scrolled to show the entire frame. If the frame is too
* large, the top and left edges are given precedence.
* * SCROLL_TOP = 0: The frame's upper edge is aligned with the
* top edge of the visible area.
* * SCROLL_BOTTOM = 100: The frame's bottom edge is aligned
* with the bottom edge of the visible area.
* * SCROLL_LEFT = 0: The frame's left edge is aligned with the
* left edge of the visible area.
* * SCROLL_RIGHT = 100: The frame's right edge is aligned with
* the right edge of the visible area.
* * SCROLL_CENTER = 50: The frame is centered along the axis
* the ScrollAxis is used for.
*
* Other values are treated as a percentage, and the point
* "percent" down the frame is placed at the point "percent"
* down the visible area.
* @param aWhen:
* * (Default) SCROLL_IF_NOT_FULLY_VISIBLE: Move the frame only
* if it is not fully visible (including if it's not visible
* at all). Note that in this case if the frame is too large to
* fit in view, it will only be scrolled if more of it can fit
* than is already in view.
* * SCROLL_IF_NOT_VISIBLE: Move the frame only if none of it
* is visible.
* * SCROLL_ALWAYS: Move the frame regardless of its current
* visibility.
*/
ScrollAxis(PRInt16 aWhere = SCROLL_MINIMUM,
WhenToScroll aWhen = SCROLL_IF_NOT_FULLY_VISIBLE) :
mWhereToScroll(aWhere), mWhenToScroll(aWhen) {}
} ScrollAxis;
/** /**
* Scrolls the view of the document so that the primary frame of the content * Scrolls the view of the document so that the primary frame of the content
* is displayed in the window. Layout is flushed before scrolling. * is displayed in the window. Layout is flushed before scrolling.
* *
* @param aContent The content object of which primary frame should be * @param aContent The content object of which primary frame should be
* scrolled into view. * scrolled into view.
* @param aVPercent How to align the frame vertically. A value of 0 * @param aVertical How to align the frame vertically and when to do so.
* (NS_PRESSHELL_SCROLL_TOP) means the frame's upper edge is * This is a ScrollAxis of Where and When.
* aligned with the top edge of the visible area. A value of * @param aHorizontal How to align the frame horizontally and when to do so.
* 100 (NS_PRESSHELL_SCROLL_BOTTOM) means the frame's bottom * This is a ScrollAxis of Where and When.
* edge is aligned with the bottom edge of the visible area.
* For values in between, the point "aVPercent" down the frame
* is placed at the point "aVPercent" down the visible area. A
* value of 50 (NS_PRESSHELL_SCROLL_CENTER) centers the frame
* vertically. A value of NS_PRESSHELL_SCROLL_ANYWHERE means move
* the frame the minimum amount necessary in order for the entire
* frame to be visible vertically (if possible)
* @param aHPercent How to align the frame horizontally. A value of 0
* (NS_PRESSHELL_SCROLL_LEFT) means the frame's left edge is
* aligned with the left edge of the visible area. A value of
* 100 (NS_PRESSHELL_SCROLL_RIGHT) means the frame's right
* edge is aligned with the right edge of the visible area.
* For values in between, the point "aVPercent" across the frame
* is placed at the point "aVPercent" across the visible area.
* A value of 50 (NS_PRESSHELL_SCROLL_CENTER) centers the frame
* horizontally . A value of NS_PRESSHELL_SCROLL_ANYWHERE means move
* the frame the minimum amount necessary in order for the entire
* frame to be visible horizontally (if possible)
* @param aFlags If SCROLL_FIRST_ANCESTOR_ONLY is set, only the nearest * @param aFlags If SCROLL_FIRST_ANCESTOR_ONLY is set, only the nearest
* scrollable ancestor is scrolled, otherwise all * scrollable ancestor is scrolled, otherwise all
* scrollable ancestors may be scrolled if necessary. * scrollable ancestors may be scrolled if necessary.
@ -573,8 +598,8 @@ public:
* contain this document in a iframe or the like. * contain this document in a iframe or the like.
*/ */
virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent, virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, ScrollAxis aVertical,
PRIntn aHPercent, ScrollAxis aHorizontal,
PRUint32 aFlags) = 0; PRUint32 aFlags) = 0;
enum { enum {
@ -587,8 +612,8 @@ public:
* is visible, if possible. Layout is not flushed before scrolling. * is visible, if possible. Layout is not flushed before scrolling.
* *
* @param aRect relative to aFrame * @param aRect relative to aFrame
* @param aVPercent see ScrollContentIntoView * @param aVertical see ScrollContentIntoView and ScrollAxis
* @param aHPercent see ScrollContentIntoView * @param aHorizontal see ScrollContentIntoView and ScrollAxis
* @param aFlags if SCROLL_FIRST_ANCESTOR_ONLY is set, only the * @param aFlags if SCROLL_FIRST_ANCESTOR_ONLY is set, only the
* nearest scrollable ancestor is scrolled, otherwise all * nearest scrollable ancestor is scrolled, otherwise all
* scrollable ancestors may be scrolled if necessary * scrollable ancestors may be scrolled if necessary
@ -602,10 +627,10 @@ public:
* @return true if any scrolling happened, false if no scrolling happened * @return true if any scrolling happened, false if no scrolling happened
*/ */
virtual bool ScrollFrameRectIntoView(nsIFrame* aFrame, virtual bool ScrollFrameRectIntoView(nsIFrame* aFrame,
const nsRect& aRect, const nsRect& aRect,
PRIntn aVPercent, ScrollAxis aVertical,
PRIntn aHPercent, ScrollAxis aHorizontal,
PRUint32 aFlags) = 0; PRUint32 aFlags) = 0;
/** /**
* Determine if a rectangle specified in the frame's coordinate system * Determine if a rectangle specified in the frame's coordinate system

View File

@ -3032,8 +3032,9 @@ PresShell::GoToAnchor(const nsAString& aAnchorName, bool aScroll)
if (content) { if (content) {
if (aScroll) { if (aScroll) {
rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_TOP, rv = ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_ANYWHERE, ScrollAxis(SCROLL_TOP, SCROLL_ALWAYS),
ScrollAxis(),
ANCHOR_SCROLL_FLAGS); ANCHOR_SCROLL_FLAGS);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -3122,8 +3123,9 @@ PresShell::ScrollToAnchor()
mLastAnchorScrollPositionY != rootScroll->GetScrollPosition().y) mLastAnchorScrollPositionY != rootScroll->GetScrollPosition().y)
return NS_OK; return NS_OK;
nsresult rv = ScrollContentIntoView(mLastAnchorScrolledTo, NS_PRESSHELL_SCROLL_TOP, nsresult rv = ScrollContentIntoView(mLastAnchorScrolledTo,
NS_PRESSHELL_SCROLL_ANYWHERE, ScrollAxis(SCROLL_TOP, SCROLL_ALWAYS),
ScrollAxis(),
ANCHOR_SCROLL_FLAGS); ANCHOR_SCROLL_FLAGS);
mLastAnchorScrolledTo = nsnull; mLastAnchorScrolledTo = nsnull;
return rv; return rv;
@ -3211,6 +3213,58 @@ AccumulateFrameBounds(nsIFrame* aContainerFrame,
} }
} }
static bool
ComputeNeedToScroll(nsIPresShell::WhenToScroll aWhenToScroll,
nscoord aLineSize,
nscoord aRectMin,
nscoord aRectMax,
nscoord aViewMin,
nscoord aViewMax) {
// See how the rect should be positioned vertically
if (nsIPresShell::SCROLL_ALWAYS == aWhenToScroll) {
// The caller wants the frame as visible as possible
return true;
} else if (nsIPresShell::SCROLL_IF_NOT_VISIBLE == aWhenToScroll) {
// Scroll only if no part of the frame is visible in this view
return aRectMax - aLineSize <= aViewMin ||
aRectMin + aLineSize >= aViewMax;
} else if (nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE == aWhenToScroll) {
// Scroll only if part of the frame is hidden and more can fit in view
return !(aRectMin >= aViewMin && aRectMax <= aViewMax) &&
NS_MIN(aViewMax, aRectMax) - NS_MAX(aRectMin, aViewMin) < aViewMax - aViewMin;
}
return false;
}
static nscoord
ComputeWhereToScroll(PRInt16 aWhereToScroll,
nscoord aOriginalCoord,
nscoord aRectMin,
nscoord aRectMax,
nscoord aViewMin,
nscoord aViewMax) {
nscoord resultCoord = aOriginalCoord;
if (nsIPresShell::SCROLL_MINIMUM == aWhereToScroll) {
if (aRectMin < aViewMin) {
// Scroll up so the frame's top edge is visible
resultCoord = aRectMin;
} else if (aRectMax > aViewMax) {
// Scroll down so the frame's bottom edge is visible. Make sure the
// frame's top edge is still visible
resultCoord = aOriginalCoord + aRectMax - aViewMax;
if (resultCoord > aRectMin) {
resultCoord = aRectMin;
}
}
} else {
nscoord frameAlignCoord =
NSToCoordRound(aRectMin + (aRectMax - aRectMin) * (aWhereToScroll / 100.0f));
resultCoord = NSToCoordRound(frameAlignCoord - (aViewMax - aViewMin) * (
aWhereToScroll / 100.0f));
}
return resultCoord;
}
/** /**
* This function takes a scrollable frame, a rect in the coordinate system * This function takes a scrollable frame, a rect in the coordinate system
* of the scrolled frame, and a desired percentage-based scroll * of the scrolled frame, and a desired percentage-based scroll
@ -3219,11 +3273,11 @@ AccumulateFrameBounds(nsIFrame* aContainerFrame,
* *
* This needs to work even if aRect has a width or height of zero. * This needs to work even if aRect has a width or height of zero.
*/ */
static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame, static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame,
const nsRect& aRect, const nsRect& aRect,
PRIntn aVPercent, nsIPresShell::ScrollAxis aVertical,
PRIntn aHPercent, nsIPresShell::ScrollAxis aHorizontal,
PRUint32 aFlags) PRUint32 aFlags)
{ {
nsPoint scrollPt = aScrollFrame->GetScrollPosition(); nsPoint scrollPt = aScrollFrame->GetScrollPosition();
nsRect visibleRect(scrollPt, aScrollFrame->GetScrollPortRect().Size()); nsRect visibleRect(scrollPt, aScrollFrame->GetScrollPortRect().Size());
@ -3232,83 +3286,37 @@ static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame,
if ((aFlags & nsIPresShell::SCROLL_OVERFLOW_HIDDEN) || if ((aFlags & nsIPresShell::SCROLL_OVERFLOW_HIDDEN) ||
ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) { ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) {
// See how the rect should be positioned vertically
if (NS_PRESSHELL_SCROLL_ANYWHERE == aVPercent || if (ComputeNeedToScroll(aVertical.mWhenToScroll,
(NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aVPercent && lineSize.height,
aRect.height < lineSize.height)) { aRect.y,
// The caller doesn't care where the frame is positioned vertically, aRect.YMost(),
// so long as it's fully visible visibleRect.y,
if (aRect.y < visibleRect.y) { visibleRect.YMost())) {
// Scroll up so the frame's top edge is visible scrollPt.y = ComputeWhereToScroll(aVertical.mWhereToScroll,
scrollPt.y = aRect.y; scrollPt.y,
} else if (aRect.YMost() > visibleRect.YMost()) { aRect.y,
// Scroll down so the frame's bottom edge is visible. Make sure the aRect.YMost(),
// frame's top edge is still visible visibleRect.y,
scrollPt.y += aRect.YMost() - visibleRect.YMost(); visibleRect.YMost());
if (scrollPt.y > aRect.y) {
scrollPt.y = aRect.y;
}
}
} else if (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aVPercent) {
// Scroll only if no part of the frame is visible in this view
if (aRect.YMost() - lineSize.height < visibleRect.y) {
// Scroll up so the frame's top edge is visible
scrollPt.y = aRect.y;
} else if (aRect.y + lineSize.height > visibleRect.YMost()) {
// Scroll down so the frame's bottom edge is visible. Make sure the
// frame's top edge is still visible
scrollPt.y += aRect.YMost() - visibleRect.YMost();
if (scrollPt.y > aRect.y) {
scrollPt.y = aRect.y;
}
}
} else {
// Align the frame edge according to the specified percentage
nscoord frameAlignY =
NSToCoordRound(aRect.y + aRect.height * (aVPercent / 100.0f));
scrollPt.y =
NSToCoordRound(frameAlignY - visibleRect.height * (aVPercent / 100.0f));
} }
} }
if ((aFlags & nsIPresShell::SCROLL_OVERFLOW_HIDDEN) || if ((aFlags & nsIPresShell::SCROLL_OVERFLOW_HIDDEN) ||
ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) { ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) {
// See how the frame should be positioned horizontally
if (NS_PRESSHELL_SCROLL_ANYWHERE == aHPercent || if (ComputeNeedToScroll(aHorizontal.mWhenToScroll,
(NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aHPercent && lineSize.width,
aRect.width < lineSize.width)) { aRect.x,
// The caller doesn't care where the frame is positioned horizontally, aRect.XMost(),
// so long as it's fully visible visibleRect.x,
if (aRect.x < visibleRect.x) { visibleRect.XMost())) {
// Scroll left so the frame's left edge is visible scrollPt.x = ComputeWhereToScroll(aHorizontal.mWhereToScroll,
scrollPt.x = aRect.x; scrollPt.x,
} else if (aRect.XMost() > visibleRect.XMost()) { aRect.x,
// Scroll right so the frame's right edge is visible. Make sure the aRect.XMost(),
// frame's left edge is still visible visibleRect.x,
scrollPt.x += aRect.XMost() - visibleRect.XMost(); visibleRect.XMost());
if (scrollPt.x > aRect.x) {
scrollPt.x = aRect.x;
}
}
} else if (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aHPercent) {
// Scroll only if no part of the frame is visible in this view
if (aRect.XMost() - lineSize.width < visibleRect.x) {
// Scroll left so the frame's left edge is visible
scrollPt.x = aRect.x;
} else if (aRect.x + lineSize.width > visibleRect.XMost()) {
// Scroll right so the frame's right edge is visible. Make sure the
// frame's left edge is still visible
scrollPt.x += aRect.XMost() - visibleRect.XMost();
if (scrollPt.x > aRect.x) {
scrollPt.x = aRect.x;
}
}
} else {
// Align the frame edge according to the specified percentage
nscoord frameAlignX =
NSToCoordRound(aRect.x + (aRect.width) * (aHPercent / 100.0f));
scrollPt.x =
NSToCoordRound(frameAlignX - visibleRect.width * (aHPercent / 100.0f));
} }
} }
@ -3316,10 +3324,10 @@ static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame,
} }
nsresult nsresult
PresShell::ScrollContentIntoView(nsIContent* aContent, PresShell::ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, nsIPresShell::ScrollAxis aVertical,
PRIntn aHPercent, nsIPresShell::ScrollAxis aHorizontal,
PRUint32 aFlags) PRUint32 aFlags)
{ {
nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing. nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing.
NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
@ -3329,8 +3337,8 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now"); NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
mContentToScrollTo = aContent; mContentToScrollTo = aContent;
mContentScrollVPosition = aVPercent; mContentScrollVAxis = aVertical;
mContentScrollHPosition = aHPercent; mContentScrollHAxis = aHorizontal;
mContentToScrollToFlags = aFlags; mContentToScrollToFlags = aFlags;
// Flush layout and attempt to scroll in the process. // Flush layout and attempt to scroll in the process.
@ -3346,16 +3354,16 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
// than a single best-effort scroll followed by one final scroll on the first // than a single best-effort scroll followed by one final scroll on the first
// completed reflow. // completed reflow.
if (mContentToScrollTo) { if (mContentToScrollTo) {
DoScrollContentIntoView(content, aVPercent, aHPercent, aFlags); DoScrollContentIntoView(content, aVertical, aHorizontal, aFlags);
} }
return NS_OK; return NS_OK;
} }
void void
PresShell::DoScrollContentIntoView(nsIContent* aContent, PresShell::DoScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, nsIPresShell::ScrollAxis aVertical,
PRIntn aHPercent, nsIPresShell::ScrollAxis aHorizontal,
PRUint32 aFlags) PRUint32 aFlags)
{ {
NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now"); NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
@ -3391,7 +3399,7 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent,
// even if that assumption was false.) // even if that assumption was false.)
nsRect frameBounds; nsRect frameBounds;
bool haveRect = false; bool haveRect = false;
bool useWholeLineHeightForInlines = aVPercent != NS_PRESSHELL_SCROLL_ANYWHERE; bool useWholeLineHeightForInlines = aVertical.mWhenToScroll != nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
// Reuse the same line iterator across calls to AccumulateFrameBounds. We set // Reuse the same line iterator across calls to AccumulateFrameBounds. We set
// it every time we detect a new block (stored in prevBlock). // it every time we detect a new block (stored in prevBlock).
nsIFrame* prevBlock = nsnull; nsIFrame* prevBlock = nsnull;
@ -3404,16 +3412,16 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent,
frameBounds, haveRect, prevBlock, lines, curLine); frameBounds, haveRect, prevBlock, lines, curLine);
} while ((frame = frame->GetNextContinuation())); } while ((frame = frame->GetNextContinuation()));
ScrollFrameRectIntoView(container, frameBounds, aVPercent, aHPercent, ScrollFrameRectIntoView(container, frameBounds, aVertical, aHorizontal,
aFlags); aFlags);
} }
bool bool
PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame, PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame,
const nsRect& aRect, const nsRect& aRect,
PRIntn aVPercent, nsIPresShell::ScrollAxis aVertical,
PRIntn aHPercent, nsIPresShell::ScrollAxis aHorizontal,
PRUint32 aFlags) PRUint32 aFlags)
{ {
bool didScroll = false; bool didScroll = false;
// This function needs to work even if rect has a width or height of 0. // This function needs to work even if rect has a width or height of 0.
@ -3426,7 +3434,7 @@ PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame,
if (sf) { if (sf) {
nsPoint oldPosition = sf->GetScrollPosition(); nsPoint oldPosition = sf->GetScrollPosition();
ScrollToShowRect(sf, rect - sf->GetScrolledFrame()->GetPosition(), ScrollToShowRect(sf, rect - sf->GetScrolledFrame()->GetPosition(),
aVPercent, aHPercent, aFlags); aVertical, aHorizontal, aFlags);
nsPoint newPosition = sf->GetScrollPosition(); nsPoint newPosition = sf->GetScrollPosition();
// If the scroll position increased, that means our content moved up, // If the scroll position increased, that means our content moved up,
// so our rect's offset should decrease // so our rect's offset should decrease
@ -3999,8 +4007,9 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
mViewManager->FlushDelayedResize(true); mViewManager->FlushDelayedResize(true);
if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) { if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) {
// We didn't get interrupted. Go ahead and scroll to our content // We didn't get interrupted. Go ahead and scroll to our content
DoScrollContentIntoView(mContentToScrollTo, mContentScrollVPosition, DoScrollContentIntoView(mContentToScrollTo,
mContentScrollHPosition, mContentScrollVAxis,
mContentScrollHAxis,
mContentToScrollToFlags); mContentToScrollToFlags);
mContentToScrollTo = nsnull; mContentToScrollTo = nsnull;
} }
@ -6878,9 +6887,10 @@ PresShell::PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& aTarge
// problem. The only difference in the result is that if your cursor is in // problem. The only difference in the result is that if your cursor is in
// an edit box below the current view, you'll get the edit box aligned with // an edit box below the current view, you'll get the edit box aligned with
// the top of the window. This is arguably better behavior anyway. // the top of the window. This is arguably better behavior anyway.
rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, rv = ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, ScrollAxis(),
SCROLL_OVERFLOW_HIDDEN); ScrollAxis(),
SCROLL_OVERFLOW_HIDDEN);
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, false);
frame = content->GetPrimaryFrame(); frame = content->GetPrimaryFrame();
NS_WARN_IF_FALSE(frame, "No frame for focused content?"); NS_WARN_IF_FALSE(frame, "No frame for focused content?");
@ -6942,9 +6952,10 @@ PresShell::GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl,
nsIWidget *aRootWidget) nsIWidget *aRootWidget)
{ {
nsCOMPtr<nsIContent> focusedContent(do_QueryInterface(aCurrentEl)); nsCOMPtr<nsIContent> focusedContent(do_QueryInterface(aCurrentEl));
ScrollContentIntoView(focusedContent, NS_PRESSHELL_SCROLL_ANYWHERE, ScrollContentIntoView(focusedContent,
NS_PRESSHELL_SCROLL_ANYWHERE, ScrollAxis(),
SCROLL_OVERFLOW_HIDDEN); ScrollAxis(),
SCROLL_OVERFLOW_HIDDEN);
nsPresContext* presContext = GetPresContext(); nsPresContext* presContext = GetPresContext();

View File

@ -248,14 +248,14 @@ public:
virtual NS_HIDDEN_(nsresult) ScrollToAnchor(); virtual NS_HIDDEN_(nsresult) ScrollToAnchor();
virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent, virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, ScrollAxis aVertical,
PRIntn aHPercent, ScrollAxis aHorizontal,
PRUint32 aFlags); PRUint32 aFlags);
virtual bool ScrollFrameRectIntoView(nsIFrame* aFrame, virtual bool ScrollFrameRectIntoView(nsIFrame* aFrame,
const nsRect& aRect, const nsRect& aRect,
PRIntn aVPercent, ScrollAxis aVertical,
PRIntn aHPercent, ScrollAxis aHorizontal,
PRUint32 aFlags); PRUint32 aFlags);
virtual nsRectVisibility GetRectVisibility(nsIFrame *aFrame, virtual nsRectVisibility GetRectVisibility(nsIFrame *aFrame,
const nsRect &aRect, const nsRect &aRect,
nscoord aMinTwips) const; nscoord aMinTwips) const;
@ -493,8 +493,8 @@ protected:
// Helper for ScrollContentIntoView // Helper for ScrollContentIntoView
void DoScrollContentIntoView(nsIContent* aContent, void DoScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, ScrollAxis aVertical,
PRIntn aHPercent, ScrollAxis aHorizontal,
PRUint32 aFlags); PRUint32 aFlags);
friend struct AutoRenderingStateSaveRestore; friend struct AutoRenderingStateSaveRestore;
@ -672,8 +672,8 @@ protected:
// processing all our dirty roots. mContentScrollVPosition and // processing all our dirty roots. mContentScrollVPosition and
// mContentScrollHPosition are only used when it's non-null. // mContentScrollHPosition are only used when it's non-null.
nsCOMPtr<nsIContent> mContentToScrollTo; nsCOMPtr<nsIContent> mContentToScrollTo;
PRIntn mContentScrollVPosition; ScrollAxis mContentScrollVAxis;
PRIntn mContentScrollHPosition; ScrollAxis mContentScrollHAxis;
PRUint32 mContentToScrollToFlags; PRUint32 mContentToScrollToFlags;
class nsDelayedEvent class nsDelayedEvent

View File

@ -206,10 +206,11 @@ public:
// The 'position' is a zero-width rectangle. // The 'position' is a zero-width rectangle.
nsIFrame* GetSelectionEndPointGeometry(SelectionRegion aRegion, nsRect *aRect); nsIFrame* GetSelectionEndPointGeometry(SelectionRegion aRegion, nsRect *aRect);
nsresult PostScrollSelectionIntoViewEvent(SelectionRegion aRegion, nsresult PostScrollSelectionIntoViewEvent(
bool aFirstAncestorOnly, SelectionRegion aRegion,
PRInt16 aVPercent, bool aFirstAncestorOnly,
PRInt16 aHPercent); nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal);
enum { enum {
SCROLL_SYNCHRONOUS = 1<<1, SCROLL_SYNCHRONOUS = 1<<1,
SCROLL_FIRST_ANCESTOR_ONLY = 1<<2, SCROLL_FIRST_ANCESTOR_ONLY = 1<<2,
@ -218,8 +219,10 @@ public:
// aDoFlush only matters if aIsSynchronous is true. If not, we'll just flush // aDoFlush only matters if aIsSynchronous is true. If not, we'll just flush
// when the scroll event fires so we make sure to scroll to the right place. // when the scroll event fires so we make sure to scroll to the right place.
nsresult ScrollIntoView(SelectionRegion aRegion, nsresult ScrollIntoView(SelectionRegion aRegion,
PRInt16 aVPercent = NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis aVertical =
PRInt16 aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(),
nsIPresShell::ScrollAxis aHorizontal =
nsIPresShell::ScrollAxis(),
PRInt32 aFlags = 0); PRInt32 aFlags = 0);
nsresult SubtractRange(RangeData* aRange, nsRange* aSubtract, nsresult SubtractRange(RangeData* aRange, nsRange* aSubtract,
nsTArray<RangeData>* aOutput); nsTArray<RangeData>* aOutput);
@ -286,23 +289,23 @@ private:
NS_DECL_NSIRUNNABLE NS_DECL_NSIRUNNABLE
ScrollSelectionIntoViewEvent(nsTypedSelection *aTypedSelection, ScrollSelectionIntoViewEvent(nsTypedSelection *aTypedSelection,
SelectionRegion aRegion, SelectionRegion aRegion,
PRInt16 aVScroll, nsIPresShell::ScrollAxis aVertical,
PRInt16 aHScroll, nsIPresShell::ScrollAxis aHorizontal,
bool aFirstAncestorOnly) bool aFirstAncestorOnly)
: mTypedSelection(aTypedSelection), : mTypedSelection(aTypedSelection),
mRegion(aRegion), mRegion(aRegion),
mVerticalScroll(aVScroll), mVerticalScroll(aVertical),
mHorizontalScroll(aHScroll), mHorizontalScroll(aHorizontal),
mFirstAncestorOnly(aFirstAncestorOnly) { mFirstAncestorOnly(aFirstAncestorOnly) {
NS_ASSERTION(aTypedSelection, "null parameter"); NS_ASSERTION(aTypedSelection, "null parameter");
} }
void Revoke() { mTypedSelection = nsnull; } void Revoke() { mTypedSelection = nsnull; }
private: private:
nsTypedSelection *mTypedSelection; nsTypedSelection *mTypedSelection;
SelectionRegion mRegion; SelectionRegion mRegion;
PRInt16 mVerticalScroll; nsIPresShell::ScrollAxis mVerticalScroll;
PRInt16 mHorizontalScroll; nsIPresShell::ScrollAxis mHorizontalScroll;
bool mFirstAncestorOnly; bool mFirstAncestorOnly;
}; };
void setAnchorFocusRange(PRInt32 aIndex); // pass in index into mRanges; void setAnchorFocusRange(PRInt32 aIndex); // pass in index into mRanges;
@ -1970,7 +1973,7 @@ nsFrameSelection::ScrollSelectionIntoView(SelectionType aType,
if (!mDomSelections[index]) if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
PRInt16 verticalScroll = PRInt16(NS_PRESSHELL_SCROLL_ANYWHERE); nsIPresShell::ScrollAxis verticalScroll = nsIPresShell::ScrollAxis();
PRInt32 flags = nsTypedSelection::SCROLL_DO_FLUSH; PRInt32 flags = nsTypedSelection::SCROLL_DO_FLUSH;
if (aFlags & nsISelectionController::SCROLL_SYNCHRONOUS) { if (aFlags & nsISelectionController::SCROLL_SYNCHRONOUS) {
flags |= nsTypedSelection::SCROLL_SYNCHRONOUS; flags |= nsTypedSelection::SCROLL_SYNCHRONOUS;
@ -1978,14 +1981,15 @@ nsFrameSelection::ScrollSelectionIntoView(SelectionType aType,
flags |= nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY; flags |= nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY;
} }
if (aFlags & nsISelectionController::SCROLL_CENTER_VERTICALLY) { if (aFlags & nsISelectionController::SCROLL_CENTER_VERTICALLY) {
verticalScroll = PRInt16(NS_PRESSHELL_SCROLL_CENTER); verticalScroll = nsIPresShell::ScrollAxis(
nsIPresShell::SCROLL_CENTER, nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE);
} }
// After ScrollSelectionIntoView(), the pending notifications might be // After ScrollSelectionIntoView(), the pending notifications might be
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470. // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
return mDomSelections[index]->ScrollIntoView(aRegion, return mDomSelections[index]->ScrollIntoView(aRegion,
verticalScroll, verticalScroll,
PRInt16(NS_PRESSHELL_SCROLL_ANYWHERE), nsIPresShell::ScrollAxis(),
flags); flags);
} }
@ -4667,10 +4671,12 @@ nsTypedSelection::DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint)
// about to do will change the coordinates of aFrame. // about to do will change the coordinates of aFrame.
nsPoint globalPoint = aPoint + aFrame->GetOffsetToCrossDoc(rootmostFrame); nsPoint globalPoint = aPoint + aFrame->GetOffsetToCrossDoc(rootmostFrame);
bool didScroll = presContext->PresShell()-> bool didScroll = presContext->PresShell()->ScrollFrameRectIntoView(
ScrollFrameRectIntoView(aFrame, nsRect(aPoint, nsSize(1,1)), aFrame,
NS_PRESSHELL_SCROLL_ANYWHERE, nsRect(aPoint, nsSize(1,1)),
NS_PRESSHELL_SCROLL_ANYWHERE, 0); nsIPresShell::ScrollAxis(),
nsIPresShell::ScrollAxis(),
0);
// //
// Start the AutoScroll timer if necessary. // Start the AutoScroll timer if necessary.
@ -5540,10 +5546,11 @@ nsTypedSelection::ScrollSelectionIntoViewEvent::Run()
} }
nsresult nsresult
nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion, nsTypedSelection::PostScrollSelectionIntoViewEvent(
bool aFirstAncestorOnly, SelectionRegion aRegion,
PRInt16 aVPercent, bool aFirstAncestorOnly,
PRInt16 aHPercent) nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal)
{ {
// If we've already posted an event, revoke it and place a new one at the // If we've already posted an event, revoke it and place a new one at the
// end of the queue to make sure that any new pending reflow events are // end of the queue to make sure that any new pending reflow events are
@ -5552,7 +5559,7 @@ nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion,
mScrollEvent.Revoke(); mScrollEvent.Revoke();
nsRefPtr<ScrollSelectionIntoViewEvent> ev = nsRefPtr<ScrollSelectionIntoViewEvent> ev =
new ScrollSelectionIntoViewEvent(this, aRegion, aVPercent, aHPercent, new ScrollSelectionIntoViewEvent(this, aRegion, aVertical, aHorizontal,
aFirstAncestorOnly); aFirstAncestorOnly);
nsresult rv = NS_DispatchToCurrentThread(ev); nsresult rv = NS_DispatchToCurrentThread(ev);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -5562,16 +5569,31 @@ nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion, bool aIsSynchronous, nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
PRInt16 aVPercent, PRInt16 aHPercent) bool aIsSynchronous,
PRInt16 aVPercent,
PRInt16 aHPercent)
{ {
return ScrollIntoView(aRegion, aVPercent, aHPercent, return ScrollIntoViewInternal(aRegion,
aIsSynchronous,
nsIPresShell::ScrollAxis(aVPercent),
nsIPresShell::ScrollAxis(aHPercent));
}
NS_IMETHODIMP
nsTypedSelection::ScrollIntoViewInternal(SelectionRegion aRegion,
bool aIsSynchronous,
nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal)
{
return ScrollIntoView(aRegion, aVertical, aHorizontal,
aIsSynchronous ? nsTypedSelection::SCROLL_SYNCHRONOUS : 0); aIsSynchronous ? nsTypedSelection::SCROLL_SYNCHRONOUS : 0);
} }
nsresult nsresult
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion, nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
PRInt16 aVPercent, PRInt16 aHPercent, nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal,
PRInt32 aFlags) PRInt32 aFlags)
{ {
nsresult result; nsresult result;
@ -5584,7 +5606,7 @@ nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
if (!(aFlags & nsTypedSelection::SCROLL_SYNCHRONOUS)) if (!(aFlags & nsTypedSelection::SCROLL_SYNCHRONOUS))
return PostScrollSelectionIntoViewEvent(aRegion, return PostScrollSelectionIntoViewEvent(aRegion,
!!(aFlags & nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY), !!(aFlags & nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY),
aVPercent, aHPercent); aVertical, aHorizontal);
// //
// Shut the caret off before scrolling to avoid // Shut the caret off before scrolling to avoid
@ -5622,7 +5644,7 @@ nsTypedSelection::ScrollIntoView(SelectionRegion aRegion,
if (!frame) if (!frame)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
presShell->ScrollFrameRectIntoView(frame, rect, aVPercent, aHPercent, presShell->ScrollFrameRectIntoView(frame, rect, aVertical, aHorizontal,
(aFlags & nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY) ? nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY: 0); (aFlags & nsTypedSelection::SCROLL_FIRST_ANCESTOR_ONLY) ? nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY: 0);
return NS_OK; return NS_OK;
} }

View File

@ -195,8 +195,8 @@ inFlasher::ScrollElementIntoView(nsIDOMElement *aElement)
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement); nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
presShell->ScrollContentIntoView(content, presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_ANYWHERE /* VPercent */, nsIPresShell::ScrollAxis(),
NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */, nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK; return NS_OK;

View File

@ -1480,13 +1480,13 @@ nsIScrollableFrame* nsMenuPopupFrame::GetScrollFrame(nsIFrame* aStart)
void nsMenuPopupFrame::EnsureMenuItemIsVisible(nsMenuFrame* aMenuItem) void nsMenuPopupFrame::EnsureMenuItemIsVisible(nsMenuFrame* aMenuItem)
{ {
if (aMenuItem) { if (aMenuItem) {
aMenuItem->PresContext()->PresShell()-> aMenuItem->PresContext()->PresShell()->ScrollFrameRectIntoView(
ScrollFrameRectIntoView(aMenuItem, aMenuItem,
nsRect(nsPoint(0,0), aMenuItem->GetRect().Size()), nsRect(nsPoint(0,0), aMenuItem->GetRect().Size()),
NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(),
NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN | nsIPresShell::SCROLL_OVERFLOW_HIDDEN |
nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY); nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY);
} }
} }

View File

@ -263,8 +263,12 @@ NS_IMETHODIMP nsScrollBoxObject::ScrollToElement(nsIDOMElement *child)
nsCOMPtr<nsIContent> content = do_QueryInterface(child); nsCOMPtr<nsIContent> content = do_QueryInterface(child);
shell->ScrollContentIntoView(content, shell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_TOP, nsIPresShell::ScrollAxis(
NS_PRESSHELL_SCROLL_LEFT, nsIPresShell::SCROLL_TOP,
nsIPresShell::SCROLL_ALWAYS),
nsIPresShell::ScrollAxis(
nsIPresShell::SCROLL_LEFT,
nsIPresShell::SCROLL_ALWAYS),
nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY | nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK; return NS_OK;
@ -317,8 +321,8 @@ NS_IMETHODIMP nsScrollBoxObject::EnsureElementIsVisible(nsIDOMElement *child)
nsCOMPtr<nsIContent> content = do_QueryInterface(child); nsCOMPtr<nsIContent> content = do_QueryInterface(child);
shell->ScrollContentIntoView(content, shell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(),
NS_PRESSHELL_SCROLL_ANYWHERE, nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY | nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK; return NS_OK;

View File

@ -335,8 +335,8 @@ nsFormFillController::SetPopupOpen(bool aPopupOpen)
docShell->GetPresShell(getter_AddRefs(presShell)); docShell->GetPresShell(getter_AddRefs(presShell));
NS_ENSURE_STATE(presShell); NS_ENSURE_STATE(presShell);
presShell->ScrollContentIntoView(content, presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, nsIPresShell::ScrollAxis(),
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN); nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
// mFocusedPopup can be destroyed after ScrollContentIntoView, see bug 420089 // mFocusedPopup can be destroyed after ScrollContentIntoView, see bug 420089
if (mFocusedPopup) if (mFocusedPopup)