From 2ec5e837c2027e33d8230796af1e665fd0950bc5 Mon Sep 17 00:00:00 2001 From: "mats.palmgren%bredband.net" Date: Fri, 6 Aug 2004 15:55:17 +0000 Subject: [PATCH] Fix keyboard scrolling for elements using overflow:scroll by scrolling the nearest scrollable view from the caret. b=251986 r=roc sr=dbaron --- content/base/src/nsSelection.cpp | 53 +------- content/events/public/nsIEventStateManager.h | 2 + content/events/src/nsEventStateManager.cpp | 31 ++--- content/events/src/nsEventStateManager.h | 1 - layout/base/nsLayoutUtils.cpp | 16 +++ layout/base/nsLayoutUtils.h | 10 ++ layout/base/nsPresShell.cpp | 121 ++++++++++--------- layout/base/public/nsLayoutUtils.h | 10 ++ layout/base/src/nsLayoutUtils.cpp | 16 +++ layout/generic/nsSelection.cpp | 53 +------- layout/html/base/src/nsPresShell.cpp | 121 ++++++++++--------- 11 files changed, 203 insertions(+), 231 deletions(-) diff --git a/content/base/src/nsSelection.cpp b/content/base/src/nsSelection.cpp index 786fed5d9084..8e4000f684cd 100644 --- a/content/base/src/nsSelection.cpp +++ b/content/base/src/nsSelection.cpp @@ -74,6 +74,7 @@ #include "nsILineIterator.h" #include "nsLayoutAtoms.h" #include "nsIFrameTraversal.h" +#include "nsLayoutUtils.h" #include "nsLayoutCID.h" static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID); @@ -245,7 +246,6 @@ public: nsresult ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool *aDidScroll); nsresult ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool aScrollParentViews, PRBool *aDidScroll); nsresult GetViewAncestorOffset(nsIView *aView, nsIView *aAncestorView, nscoord *aXOffset, nscoord *aYOffset); - nsresult GetClosestScrollableView(nsIView *aView, nsIScrollableView **aScrollableView); SelectionType GetType(){return mType;} void SetType(SelectionType aType){mType = aType;} @@ -5284,26 +5284,6 @@ nsTypedSelection::GetViewAncestorOffset(nsIView *aView, nsIView *aAncestorView, return NS_OK; } -nsresult -nsTypedSelection::GetClosestScrollableView(nsIView *aView, nsIScrollableView **aScrollableView) -{ - if (!aView || !aScrollableView) - return NS_ERROR_FAILURE; - - *aScrollableView = 0; - - while (!*aScrollableView && aView) - { - CallQueryInterface(aView, aScrollableView); - if (!*aScrollableView) - { - aView = aView->GetParent(); - } - } - - return NS_OK; -} - nsresult nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool *aDidScroll) { @@ -5318,12 +5298,7 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * // Get aView's scrollable view. // - nsIScrollableView *scrollableView = 0; - - result = GetClosestScrollableView(aView, &scrollableView); - - if (NS_FAILED(result)) - return result; + nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); if (!scrollableView) return NS_OK; // Nothing to do! @@ -5513,12 +5488,7 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie // Find aView's parent scrollable view. // - nsIScrollableView *scrollableView = 0; - - result = GetClosestScrollableView(aView, &scrollableView); - - if (NS_FAILED(result)) - return result; + nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); if (scrollableView) { @@ -5542,10 +5512,7 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie while (view) { - result = GetClosestScrollableView(view, &scrollableView); - - if (NS_FAILED(result)) - return result; + scrollableView = nsLayoutUtils::GetNearestScrollingView(view); if (!scrollableView) break; @@ -7015,10 +6982,7 @@ nsTypedSelection::GetSelectionRegionRectAndScrollableView(SelectionRegion aRegio nsIView* view = parentWithView->GetView(); - result = GetClosestScrollableView(view, aScrollableView); - - if (NS_FAILED(result)) - return result; + *aScrollableView = nsLayoutUtils::GetNearestScrollingView(view); if (!*aScrollableView) return NS_OK; @@ -7265,12 +7229,7 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView, if (view) { - nsIScrollableView *parentSV = 0; - - rv = GetClosestScrollableView(view, &parentSV); - - if (NS_FAILED(rv)) - return rv; + nsIScrollableView *parentSV = nsLayoutUtils::GetNearestScrollingView(view); if (parentSV) { diff --git a/content/events/public/nsIEventStateManager.h b/content/events/public/nsIEventStateManager.h index 3d30dd81824d..b609dbd6fa42 100644 --- a/content/events/public/nsIEventStateManager.h +++ b/content/events/public/nsIEventStateManager.h @@ -124,6 +124,8 @@ public: // Method for moving the focus forward/back. NS_IMETHOD ShiftFocus(PRBool aDirection, nsIContent* aStart)=0; + // Return the location of the caret + NS_IMETHOD GetDocSelectionLocation(nsIContent **startContent, nsIContent **endContent, nsIFrame **startFrame, PRUint32 *startOffset) = 0; }; #define NS_EVENT_STATE_UNSPECIFIED 0x0000 diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index c7a37764a3eb..5b07d6051ca4 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -114,6 +114,7 @@ #include "nsIFrameTraversal.h" #include "nsLayoutAtoms.h" #include "nsLayoutCID.h" +#include "nsLayoutUtils.h" #include "nsIInterfaceRequestorUtils.h" #include "nsUnicharUtils.h" #include "nsContentUtils.h" @@ -1723,7 +1724,7 @@ nsEventStateManager::DoScrollText(nsPresContext* aPresContext, if (!focusView) return NS_ERROR_FAILURE; - sv = GetNearestScrollingView(focusView); + sv = nsLayoutUtils::GetNearestScrollingView(focusView); } PRBool passToParent; @@ -2132,7 +2133,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_PAGE_DOWN: case NS_VK_PAGE_UP: if (!mCurrentFocus) { - nsIScrollableView* sv = GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByPages(0, (keyEvent->keyCode != NS_VK_PAGE_UP) ? 1 : -1); @@ -2142,7 +2143,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_HOME: case NS_VK_END: if (!mCurrentFocus) { - nsIScrollableView* sv = GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByWhole((keyEvent->keyCode != NS_VK_HOME) ? PR_FALSE : PR_TRUE); @@ -2152,7 +2153,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_DOWN: case NS_VK_UP: if (!mCurrentFocus) { - nsIScrollableView* sv = GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByLines(0, (keyEvent->keyCode == NS_VK_DOWN) ? 1 : -1); @@ -2171,7 +2172,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_LEFT: case NS_VK_RIGHT: if (!mCurrentFocus) { - nsIScrollableView* sv = GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByLines((keyEvent->keyCode == NS_VK_RIGHT) ? 1 : -1, 0); @@ -2193,7 +2194,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; if (keyEvent->charCode == 0x20) { if (!mCurrentFocus) { - nsIScrollableView* sv = GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); if (sv) { sv->ScrollByPages(0, 1); } @@ -2327,24 +2328,6 @@ nsEventStateManager::ClearFrameRefs(nsIFrame* aFrame) return NS_OK; } -nsIScrollableView* -nsEventStateManager::GetNearestScrollingView(nsIView* aView) -{ - nsIScrollableView* sv = nsnull; - CallQueryInterface(aView, &sv); - if (sv) { - return sv; - } - - nsIView* parent = aView->GetParent(); - - if (parent) { - return GetNearestScrollingView(parent); - } - - return nsnull; -} - PRBool nsEventStateManager::CheckDisabled(nsIContent* aContent) { diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index 2754302b406c..c5f3637b7ba5 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -207,7 +207,6 @@ protected: nsIDocShellTreeItem** aResult); // These functions are for mousewheel scrolling - nsIScrollableView* GetNearestScrollingView(nsIView* aView); nsresult GetParentScrollingView(nsInputEvent* aEvent, nsPresContext* aPresContext, nsIFrame* &targetOuterFrame, diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index a4978d40ec6f..ccaa656aa91f 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -44,6 +44,7 @@ #include "nsIAtom.h" #include "nsCSSPseudoElements.h" #include "nsIView.h" +#include "nsIScrollableView.h" /** * A namespace class for static layout utilities. @@ -332,3 +333,18 @@ nsLayoutUtils::FindSiblingViewFor(nsIView* aParentView, nsIFrame* aFrame) { } return nsnull; } + +// static +nsIScrollableView* +nsLayoutUtils::GetNearestScrollingView(nsIView* aView) +{ + NS_ASSERTION(aView, "GetNearestScrollingView expects a non-null view"); + nsIScrollableView* scrollableView = nsnull; + for (; aView; aView = aView->GetParent()) { + CallQueryInterface(aView, &scrollableView); + if (scrollableView) { + break; + } + } + return scrollableView; +} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 05800a869072..7ebd5cf17e9a 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -43,6 +43,7 @@ class nsPresContext; class nsIContent; class nsIAtom; class nsIView; +class nsIScrollableView; #include "prtypes.h" #include "nsStyleContext.h" @@ -163,6 +164,15 @@ public: static PRBool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame, nsIFrame* aCommonAncestor = nsnull); + /** + * GetNearestScrollingView locates the first ancestor of aView (or + * aView itself) that is scrollable. + * + * @param aView the view we're looking at + * @return the nearest scrollable view or nsnull if not found + */ + static nsIScrollableView* GetNearestScrollingView(nsIView* aView); + /** * HasPseudoStyle returns PR_TRUE if aContent (whose primary style * context is aStyleContext) has the aPseudoElement pseudo-style diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 5902fe0cd65c..6bfeb649172a 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1357,9 +1357,12 @@ protected: friend struct ReflowEvent; - // utility to determine if we're in the middle of a drag + // Utility to determine if we're in the middle of a drag. PRBool IsDragInProgress ( ) const ; + // Utility to find which view to scroll. + nsIScrollableView* GetViewToScroll(); + PRBool mCaretEnabled; #ifdef IBMBIDI PRUint8 mBidiLevel; // The Bidi level of the cursor @@ -3228,92 +3231,68 @@ PresShell::PageMove(PRBool aForward, PRBool aExtend) NS_IMETHODIMP PresShell::ScrollPage(PRBool aForward) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - scrollView->ScrollByPages(0, aForward ? 1 : -1); - } + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { + scrollView->ScrollByPages(0, aForward ? 1 : -1); } - return result; + return NS_OK; } NS_IMETHODIMP PresShell::ScrollLine(PRBool aForward) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { #ifdef MOZ_WIDGET_COCOA - // Emulate the Mac IE behavior of scrolling a minimum of 2 lines - // rather than 1. This vastly improves scrolling speed. - scrollView->ScrollByLines(0, aForward ? 2 : -2); + // Emulate the Mac IE behavior of scrolling a minimum of 2 lines + // rather than 1. This vastly improves scrolling speed. + scrollView->ScrollByLines(0, aForward ? 2 : -2); #else - scrollView->ScrollByLines(0, aForward ? 1 : -1); + scrollView->ScrollByLines(0, aForward ? 1 : -1); #endif //NEW FOR LINES - // force the update to happen now, otherwise multiple scrolls can - // occur before the update is processed. (bug #7354) + // force the update to happen now, otherwise multiple scrolls can + // occur before the update is processed. (bug #7354) - // I'd use Composite here, but it doesn't always work. - // vm->Composite(); + // I'd use Composite here, but it doesn't always work. + // vm->Composite(); + nsIViewManager* viewManager = GetViewManager(); + if (viewManager) { viewManager->ForceUpdate(); } } - - return result; + return NS_OK; } NS_IMETHODIMP PresShell::ScrollHorizontal(PRBool aLeft) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - scrollView->ScrollByLines(aLeft ? -1 : 1, 0); + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { + scrollView->ScrollByLines(aLeft ? -1 : 1, 0); //NEW FOR LINES - // force the update to happen now, otherwise multiple scrolls can - // occur before the update is processed. (bug #7354) + // force the update to happen now, otherwise multiple scrolls can + // occur before the update is processed. (bug #7354) - // I'd use Composite here, but it doesn't always work. - // vm->Composite(); + // I'd use Composite here, but it doesn't always work. + // vm->Composite(); + nsIViewManager* viewManager = GetViewManager(); + if (viewManager) { viewManager->ForceUpdate(); } } - - return result; + return NS_OK; } NS_IMETHODIMP PresShell::CompleteScroll(PRBool aForward) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - scrollView->ScrollByWhole(!aForward);//TRUE = top, aForward TRUE=bottom - } + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { + scrollView->ScrollByWhole(!aForward);//TRUE = top, aForward TRUE=bottom } - return result; + return NS_OK; } NS_IMETHODIMP @@ -3774,6 +3753,36 @@ PresShell :: IsDragInProgress ( ) const } // IsDragInProgress +nsIScrollableView* +PresShell::GetViewToScroll() +{ + nsCOMPtr esm = mPresContext->EventStateManager(); + nsIFrame* selectionFrame = nsnull; + nsIScrollableView* scrollView = nsnull; + nsCOMPtr selectionContent, endSelectionContent; // NOT USED + PRUint32 selectionOffset; // NOT USED + esm->GetDocSelectionLocation(getter_AddRefs(selectionContent), + getter_AddRefs(endSelectionContent), + &selectionFrame, + &selectionOffset); + if (selectionFrame) { + nsCOMPtr svp = do_QueryInterface(selectionFrame); + if (svp) { + svp->GetScrollableView(mPresContext, &scrollView); + } else { + nsIView* selectionView = selectionFrame->GetClosestView(); + if (selectionView) + scrollView = nsLayoutUtils::GetNearestScrollingView(selectionView); + } + } + if (!scrollView) { + nsIViewManager* viewManager = GetViewManager(); + if (viewManager) { + viewManager->GetRootScrollableView(&scrollView); + } + } + return scrollView; +} NS_IMETHODIMP PresShell::CancelReflowCommandInternal(nsIFrame* aTargetFrame, diff --git a/layout/base/public/nsLayoutUtils.h b/layout/base/public/nsLayoutUtils.h index 05800a869072..7ebd5cf17e9a 100644 --- a/layout/base/public/nsLayoutUtils.h +++ b/layout/base/public/nsLayoutUtils.h @@ -43,6 +43,7 @@ class nsPresContext; class nsIContent; class nsIAtom; class nsIView; +class nsIScrollableView; #include "prtypes.h" #include "nsStyleContext.h" @@ -163,6 +164,15 @@ public: static PRBool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame, nsIFrame* aCommonAncestor = nsnull); + /** + * GetNearestScrollingView locates the first ancestor of aView (or + * aView itself) that is scrollable. + * + * @param aView the view we're looking at + * @return the nearest scrollable view or nsnull if not found + */ + static nsIScrollableView* GetNearestScrollingView(nsIView* aView); + /** * HasPseudoStyle returns PR_TRUE if aContent (whose primary style * context is aStyleContext) has the aPseudoElement pseudo-style diff --git a/layout/base/src/nsLayoutUtils.cpp b/layout/base/src/nsLayoutUtils.cpp index a4978d40ec6f..ccaa656aa91f 100644 --- a/layout/base/src/nsLayoutUtils.cpp +++ b/layout/base/src/nsLayoutUtils.cpp @@ -44,6 +44,7 @@ #include "nsIAtom.h" #include "nsCSSPseudoElements.h" #include "nsIView.h" +#include "nsIScrollableView.h" /** * A namespace class for static layout utilities. @@ -332,3 +333,18 @@ nsLayoutUtils::FindSiblingViewFor(nsIView* aParentView, nsIFrame* aFrame) { } return nsnull; } + +// static +nsIScrollableView* +nsLayoutUtils::GetNearestScrollingView(nsIView* aView) +{ + NS_ASSERTION(aView, "GetNearestScrollingView expects a non-null view"); + nsIScrollableView* scrollableView = nsnull; + for (; aView; aView = aView->GetParent()) { + CallQueryInterface(aView, &scrollableView); + if (scrollableView) { + break; + } + } + return scrollableView; +} diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 786fed5d9084..8e4000f684cd 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -74,6 +74,7 @@ #include "nsILineIterator.h" #include "nsLayoutAtoms.h" #include "nsIFrameTraversal.h" +#include "nsLayoutUtils.h" #include "nsLayoutCID.h" static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID); @@ -245,7 +246,6 @@ public: nsresult ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool *aDidScroll); nsresult ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool aScrollParentViews, PRBool *aDidScroll); nsresult GetViewAncestorOffset(nsIView *aView, nsIView *aAncestorView, nscoord *aXOffset, nscoord *aYOffset); - nsresult GetClosestScrollableView(nsIView *aView, nsIScrollableView **aScrollableView); SelectionType GetType(){return mType;} void SetType(SelectionType aType){mType = aType;} @@ -5284,26 +5284,6 @@ nsTypedSelection::GetViewAncestorOffset(nsIView *aView, nsIView *aAncestorView, return NS_OK; } -nsresult -nsTypedSelection::GetClosestScrollableView(nsIView *aView, nsIScrollableView **aScrollableView) -{ - if (!aView || !aScrollableView) - return NS_ERROR_FAILURE; - - *aScrollableView = 0; - - while (!*aScrollableView && aView) - { - CallQueryInterface(aView, aScrollableView); - if (!*aScrollableView) - { - aView = aView->GetParent(); - } - } - - return NS_OK; -} - nsresult nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool *aDidScroll) { @@ -5318,12 +5298,7 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * // Get aView's scrollable view. // - nsIScrollableView *scrollableView = 0; - - result = GetClosestScrollableView(aView, &scrollableView); - - if (NS_FAILED(result)) - return result; + nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); if (!scrollableView) return NS_OK; // Nothing to do! @@ -5513,12 +5488,7 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie // Find aView's parent scrollable view. // - nsIScrollableView *scrollableView = 0; - - result = GetClosestScrollableView(aView, &scrollableView); - - if (NS_FAILED(result)) - return result; + nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); if (scrollableView) { @@ -5542,10 +5512,7 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie while (view) { - result = GetClosestScrollableView(view, &scrollableView); - - if (NS_FAILED(result)) - return result; + scrollableView = nsLayoutUtils::GetNearestScrollingView(view); if (!scrollableView) break; @@ -7015,10 +6982,7 @@ nsTypedSelection::GetSelectionRegionRectAndScrollableView(SelectionRegion aRegio nsIView* view = parentWithView->GetView(); - result = GetClosestScrollableView(view, aScrollableView); - - if (NS_FAILED(result)) - return result; + *aScrollableView = nsLayoutUtils::GetNearestScrollingView(view); if (!*aScrollableView) return NS_OK; @@ -7265,12 +7229,7 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView, if (view) { - nsIScrollableView *parentSV = 0; - - rv = GetClosestScrollableView(view, &parentSV); - - if (NS_FAILED(rv)) - return rv; + nsIScrollableView *parentSV = nsLayoutUtils::GetNearestScrollingView(view); if (parentSV) { diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 5902fe0cd65c..6bfeb649172a 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -1357,9 +1357,12 @@ protected: friend struct ReflowEvent; - // utility to determine if we're in the middle of a drag + // Utility to determine if we're in the middle of a drag. PRBool IsDragInProgress ( ) const ; + // Utility to find which view to scroll. + nsIScrollableView* GetViewToScroll(); + PRBool mCaretEnabled; #ifdef IBMBIDI PRUint8 mBidiLevel; // The Bidi level of the cursor @@ -3228,92 +3231,68 @@ PresShell::PageMove(PRBool aForward, PRBool aExtend) NS_IMETHODIMP PresShell::ScrollPage(PRBool aForward) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - scrollView->ScrollByPages(0, aForward ? 1 : -1); - } + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { + scrollView->ScrollByPages(0, aForward ? 1 : -1); } - return result; + return NS_OK; } NS_IMETHODIMP PresShell::ScrollLine(PRBool aForward) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { #ifdef MOZ_WIDGET_COCOA - // Emulate the Mac IE behavior of scrolling a minimum of 2 lines - // rather than 1. This vastly improves scrolling speed. - scrollView->ScrollByLines(0, aForward ? 2 : -2); + // Emulate the Mac IE behavior of scrolling a minimum of 2 lines + // rather than 1. This vastly improves scrolling speed. + scrollView->ScrollByLines(0, aForward ? 2 : -2); #else - scrollView->ScrollByLines(0, aForward ? 1 : -1); + scrollView->ScrollByLines(0, aForward ? 1 : -1); #endif //NEW FOR LINES - // force the update to happen now, otherwise multiple scrolls can - // occur before the update is processed. (bug #7354) + // force the update to happen now, otherwise multiple scrolls can + // occur before the update is processed. (bug #7354) - // I'd use Composite here, but it doesn't always work. - // vm->Composite(); + // I'd use Composite here, but it doesn't always work. + // vm->Composite(); + nsIViewManager* viewManager = GetViewManager(); + if (viewManager) { viewManager->ForceUpdate(); } } - - return result; + return NS_OK; } NS_IMETHODIMP PresShell::ScrollHorizontal(PRBool aLeft) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - scrollView->ScrollByLines(aLeft ? -1 : 1, 0); + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { + scrollView->ScrollByLines(aLeft ? -1 : 1, 0); //NEW FOR LINES - // force the update to happen now, otherwise multiple scrolls can - // occur before the update is processed. (bug #7354) + // force the update to happen now, otherwise multiple scrolls can + // occur before the update is processed. (bug #7354) - // I'd use Composite here, but it doesn't always work. - // vm->Composite(); + // I'd use Composite here, but it doesn't always work. + // vm->Composite(); + nsIViewManager* viewManager = GetViewManager(); + if (viewManager) { viewManager->ForceUpdate(); } } - - return result; + return NS_OK; } NS_IMETHODIMP PresShell::CompleteScroll(PRBool aForward) { - nsIViewManager* viewManager = GetViewManager(); - nsresult result = NS_OK; - if (viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - scrollView->ScrollByWhole(!aForward);//TRUE = top, aForward TRUE=bottom - } + nsIScrollableView* scrollView = GetViewToScroll(); + if (scrollView) { + scrollView->ScrollByWhole(!aForward);//TRUE = top, aForward TRUE=bottom } - return result; + return NS_OK; } NS_IMETHODIMP @@ -3774,6 +3753,36 @@ PresShell :: IsDragInProgress ( ) const } // IsDragInProgress +nsIScrollableView* +PresShell::GetViewToScroll() +{ + nsCOMPtr esm = mPresContext->EventStateManager(); + nsIFrame* selectionFrame = nsnull; + nsIScrollableView* scrollView = nsnull; + nsCOMPtr selectionContent, endSelectionContent; // NOT USED + PRUint32 selectionOffset; // NOT USED + esm->GetDocSelectionLocation(getter_AddRefs(selectionContent), + getter_AddRefs(endSelectionContent), + &selectionFrame, + &selectionOffset); + if (selectionFrame) { + nsCOMPtr svp = do_QueryInterface(selectionFrame); + if (svp) { + svp->GetScrollableView(mPresContext, &scrollView); + } else { + nsIView* selectionView = selectionFrame->GetClosestView(); + if (selectionView) + scrollView = nsLayoutUtils::GetNearestScrollingView(selectionView); + } + } + if (!scrollView) { + nsIViewManager* viewManager = GetViewManager(); + if (viewManager) { + viewManager->GetRootScrollableView(&scrollView); + } + } + return scrollView; +} NS_IMETHODIMP PresShell::CancelReflowCommandInternal(nsIFrame* aTargetFrame,