From feb3d9aee86a55a32c98d618993bd9cc15fd696e Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Tue, 21 Sep 2004 04:41:08 +0000 Subject: [PATCH] Don't allow the user to scroll things that are 'overflow: hidden'. b=259615 r+sr=roc --- content/base/src/nsSelection.cpp | 129 ++++++++++++--------- content/events/src/nsEventStateManager.cpp | 10 +- layout/base/nsLayoutUtils.cpp | 32 ++++- layout/base/nsLayoutUtils.h | 13 ++- layout/base/nsPresShell.cpp | 15 +-- layout/base/public/nsLayoutUtils.h | 13 ++- layout/base/src/nsLayoutUtils.cpp | 32 ++++- layout/generic/nsSelection.cpp | 129 ++++++++++++--------- layout/html/base/src/nsPresShell.cpp | 15 +-- 9 files changed, 253 insertions(+), 135 deletions(-) diff --git a/content/base/src/nsSelection.cpp b/content/base/src/nsSelection.cpp index b154d9f4e70a..73bc5388e4ff 100644 --- a/content/base/src/nsSelection.cpp +++ b/content/base/src/nsSelection.cpp @@ -5243,7 +5243,8 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * // Get aView's scrollable view. // - nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView *scrollableView = + nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eEither); if (!scrollableView) return NS_OK; // Nothing to do! @@ -5287,25 +5288,33 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * // nscoord dx = 0, dy = 0; - nsPoint ePoint = aPoint; - ePoint.x += viewOffset.x; - ePoint.y += viewOffset.y; + nsPresContext::ScrollbarStyles ss = + nsLayoutUtils::ScrollbarStylesOfView(scrollableView); + + if (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) { + nscoord e = aPoint.x + viewOffset.x; - nscoord x1 = bounds.x; - nscoord x2 = bounds.x + bounds.width; - nscoord y1 = bounds.y; - nscoord y2 = bounds.y + bounds.height; + nscoord x1 = bounds.x; + nscoord x2 = bounds.x + bounds.width; - if (ePoint.x < x1) - dx = ePoint.x - x1; - else if (ePoint.x > x2) - dx = ePoint.x - x2; - - if (ePoint.y < y1) - dy = ePoint.y - y1; - else if (ePoint.y > y2) - dy = ePoint.y - y2; + if (e < x1) + dx = e - x1; + else if (e > x2) + dx = e - x2; + } + + if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) { + nscoord e = aPoint.y + viewOffset.y; + + nscoord y1 = bounds.y; + nscoord y2 = bounds.y + bounds.height; + + if (e < y1) + dy = e - y1; + else if (e > y2) + dy = e - y2; + } // // Now clip the scroll amounts so that we don't scroll @@ -5326,7 +5335,7 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * dx = 0; else if (dx > 0) { - x1 = scrollX + dx + bounds.width; + nscoord x1 = scrollX + dx + bounds.width; if (x1 > docWidth) dx -= x1 - docWidth; @@ -5337,7 +5346,7 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * dy = 0; else if (dy > 0) { - y1 = scrollY + dy + bounds.height; + nscoord y1 = scrollY + dy + bounds.height; if (y1 > docHeight) dy -= y1 - docHeight; @@ -5420,7 +5429,8 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie // Find aView's parent scrollable view. // - nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView *scrollableView = + nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eEither); if (scrollableView) { @@ -5442,7 +5452,9 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie while (view) { - scrollableView = nsLayoutUtils::GetNearestScrollingView(view); + scrollableView = + nsLayoutUtils::GetNearestScrollingView(view, + nsLayoutUtils::eEither); if (!scrollableView) break; @@ -6886,7 +6898,8 @@ nsTypedSelection::GetSelectionRegionRectAndScrollableView(SelectionRegion aRegio nsIView* view = parentWithView->GetView(); - *aScrollableView = nsLayoutUtils::GetNearestScrollingView(view); + *aScrollableView = + nsLayoutUtils::GetNearestScrollingView(view, nsLayoutUtils::eEither); if (!*aScrollableView) return NS_OK; @@ -7049,47 +7062,54 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView, nscoord scrollOffsetX = visibleRect.x; nscoord scrollOffsetY = visibleRect.y; + nsPresContext::ScrollbarStyles ss = + nsLayoutUtils::ScrollbarStylesOfView(aScrollableView); + // See how aRect should be positioned vertically - if (NS_PRESSHELL_SCROLL_ANYWHERE == aVPercent) { - // The caller doesn't care where aRect is positioned vertically, - // so long as it's fully visible - if (aRect.y < visibleRect.y) { - // Scroll up so aRect's top edge is visible - scrollOffsetY = aRect.y; - } else if (aRect.YMost() > visibleRect.YMost()) { - // Scroll down so aRect's bottom edge is visible. Make sure - // aRect's top edge is still visible - scrollOffsetY += aRect.YMost() - visibleRect.YMost(); - if (scrollOffsetY > aRect.y) { + if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) { + if (NS_PRESSHELL_SCROLL_ANYWHERE == aVPercent) { + // The caller doesn't care where aRect is positioned vertically, + // so long as it's fully visible + if (aRect.y < visibleRect.y) { + // Scroll up so aRect's top edge is visible scrollOffsetY = aRect.y; + } else if (aRect.YMost() > visibleRect.YMost()) { + // Scroll down so aRect's bottom edge is visible. Make sure + // aRect's top edge is still visible + scrollOffsetY += aRect.YMost() - visibleRect.YMost(); + if (scrollOffsetY > aRect.y) { + scrollOffsetY = aRect.y; + } } + } else { + // Align the aRect edge according to the specified percentage + nscoord frameAlignY = aRect.y + (aRect.height * aVPercent) / 100; + scrollOffsetY = frameAlignY - (visibleRect.height * aVPercent) / 100; } - } else { - // Align the aRect edge according to the specified percentage - nscoord frameAlignY = aRect.y + (aRect.height * aVPercent) / 100; - scrollOffsetY = frameAlignY - (visibleRect.height * aVPercent) / 100; } // See how the aRect should be positioned horizontally - if (NS_PRESSHELL_SCROLL_ANYWHERE == aHPercent) { - // The caller doesn't care where the aRect is positioned horizontally, - // so long as it's fully visible - if (aRect.x < visibleRect.x) { - // Scroll left so the aRect's left edge is visible - scrollOffsetX = aRect.x; - } else if (aRect.XMost() > visibleRect.XMost()) { - // Scroll right so the aRect's right edge is visible. Make sure the - // aRect's left edge is still visible - scrollOffsetX += aRect.XMost() - visibleRect.XMost(); - if (scrollOffsetX > aRect.x) { + if (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) { + if (NS_PRESSHELL_SCROLL_ANYWHERE == aHPercent) { + // The caller doesn't care where the aRect is positioned horizontally, + // so long as it's fully visible + if (aRect.x < visibleRect.x) { + // Scroll left so the aRect's left edge is visible scrollOffsetX = aRect.x; + } else if (aRect.XMost() > visibleRect.XMost()) { + // Scroll right so the aRect's right edge is visible. Make sure the + // aRect's left edge is still visible + scrollOffsetX += aRect.XMost() - visibleRect.XMost(); + if (scrollOffsetX > aRect.x) { + scrollOffsetX = aRect.x; + } } + + } else { + // Align the aRect edge according to the specified percentage + nscoord frameAlignX = aRect.x + (aRect.width * aHPercent) / 100; + scrollOffsetX = frameAlignX - (visibleRect.width * aHPercent) / 100; } - - } else { - // Align the aRect edge according to the specified percentage - nscoord frameAlignX = aRect.x + (aRect.width * aHPercent) / 100; - scrollOffsetX = frameAlignX - (visibleRect.width * aHPercent) / 100; } aScrollableView->ScrollTo(scrollOffsetX, scrollOffsetY, NS_VMREFRESH_IMMEDIATE); @@ -7118,7 +7138,8 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView, if (view) { - nsIScrollableView *parentSV = nsLayoutUtils::GetNearestScrollingView(view); + nsIScrollableView *parentSV = + nsLayoutUtils::GetNearestScrollingView(view, nsLayoutUtils::eEither); if (parentSV) { diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 99232bce4d0d..61080a0c64e5 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -2083,7 +2083,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_PAGE_DOWN: case NS_VK_PAGE_UP: if (!mCurrentFocus) { - nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByPages(0, (keyEvent->keyCode != NS_VK_PAGE_UP) ? 1 : -1); @@ -2093,7 +2093,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_HOME: case NS_VK_END: if (!mCurrentFocus) { - nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByWhole((keyEvent->keyCode != NS_VK_HOME) ? PR_FALSE : PR_TRUE); @@ -2103,7 +2103,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_DOWN: case NS_VK_UP: if (!mCurrentFocus) { - nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByLines(0, (keyEvent->keyCode == NS_VK_DOWN) ? 1 : -1); @@ -2122,7 +2122,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, case NS_VK_LEFT: case NS_VK_RIGHT: if (!mCurrentFocus) { - nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eHorizontal); if (sv) { nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; sv->ScrollByLines((keyEvent->keyCode == NS_VK_RIGHT) ? 1 : -1, 0); @@ -2144,7 +2144,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent; if (keyEvent->charCode == 0x20) { if (!mCurrentFocus) { - nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical); if (sv) { sv->ScrollByPages(0, 1); } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 69e449d78f86..6989da12f5dd 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -46,6 +46,7 @@ #include "nsIView.h" #include "nsIScrollableView.h" #include "nsPlaceholderFrame.h" +#include "nsIScrollableFrame.h" /** * A namespace class for static layout utilities. @@ -348,16 +349,43 @@ nsLayoutUtils::FindSiblingViewFor(nsIView* aParentView, nsIFrame* aFrame) { return nsnull; } +//static +nsPresContext::ScrollbarStyles +nsLayoutUtils::ScrollbarStylesOfView(nsIScrollableView *aScrollableView) +{ + nsIView *view; + CallQueryInterface(aScrollableView, &view); + nsIFrame *frame = NS_STATIC_CAST(nsIFrame*, view->GetClientData()); + if (frame && ((frame = frame->GetParent()))) { + nsIScrollableFrame *sf; + CallQueryInterface(frame, &sf); + if (sf) + return sf->GetScrollbarStyles(); + } + return nsPresContext::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, + NS_STYLE_OVERFLOW_HIDDEN); +} + // static nsIScrollableView* -nsLayoutUtils::GetNearestScrollingView(nsIView* aView) +nsLayoutUtils::GetNearestScrollingView(nsIView* aView, Direction aDirection) { + // Find the first view that has a scrollable frame whose + // ScrollbarStyles is not NS_STYLE_OVERFLOW_HIDDEN in aDirection. NS_ASSERTION(aView, "GetNearestScrollingView expects a non-null view"); nsIScrollableView* scrollableView = nsnull; for (; aView; aView = aView->GetParent()) { CallQueryInterface(aView, &scrollableView); if (scrollableView) { - break; + nsPresContext::ScrollbarStyles ss = + nsLayoutUtils::ScrollbarStylesOfView(scrollableView); + // aDirection can be eHorizontal, eVertical, or eEither + if (aDirection != eHorizontal && + ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) + break; + if (aDirection != eVertical && + ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) + break; } } return scrollableView; diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 5e1cc200d7e2..5e305ba623c6 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -164,14 +164,23 @@ public: static PRBool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame, nsIFrame* aCommonAncestor = nsnull); + static nsPresContext::ScrollbarStyles + ScrollbarStylesOfView(nsIScrollableView *aScrollableView); + /** * GetNearestScrollingView locates the first ancestor of aView (or - * aView itself) that is scrollable. + * aView itself) that is scrollable. It does *not* count an + * 'overflow' style of 'hidden' as scrollable, even though a scrolling + * view is present. Thus, the direction of the scroll is needed as + * an argument. * * @param aView the view we're looking at + * @param aDirection Whether it's for horizontal or vertical scrolling. * @return the nearest scrollable view or nsnull if not found */ - static nsIScrollableView* GetNearestScrollingView(nsIView* aView); + enum Direction { eHorizontal, eVertical, eEither }; + static nsIScrollableView* GetNearestScrollingView(nsIView* aView, + Direction aDirection); /** * HasPseudoStyle returns PR_TRUE if aContent (whose primary style diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 7de231409ea0..e29fbcd92902 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1351,7 +1351,7 @@ protected: PRBool IsDragInProgress ( ) const ; // Utility to find which view to scroll. - nsIScrollableView* GetViewToScroll(); + nsIScrollableView* GetViewToScroll(nsLayoutUtils::Direction aDirection); PRBool mCaretEnabled; #ifdef IBMBIDI @@ -3138,7 +3138,7 @@ PresShell::PageMove(PRBool aForward, PRBool aExtend) NS_IMETHODIMP PresShell::ScrollPage(PRBool aForward) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical); if (scrollView) { scrollView->ScrollByPages(0, aForward ? 1 : -1); } @@ -3148,7 +3148,7 @@ PresShell::ScrollPage(PRBool aForward) NS_IMETHODIMP PresShell::ScrollLine(PRBool aForward) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical); if (scrollView) { #ifdef MOZ_WIDGET_COCOA // Emulate the Mac IE behavior of scrolling a minimum of 2 lines @@ -3175,7 +3175,7 @@ PresShell::ScrollLine(PRBool aForward) NS_IMETHODIMP PresShell::ScrollHorizontal(PRBool aLeft) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eHorizontal); if (scrollView) { scrollView->ScrollByLines(aLeft ? -1 : 1, 0); //NEW FOR LINES @@ -3195,7 +3195,7 @@ PresShell::ScrollHorizontal(PRBool aLeft) NS_IMETHODIMP PresShell::CompleteScroll(PRBool aForward) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical); if (scrollView) { scrollView->ScrollByWhole(!aForward);//TRUE = top, aForward TRUE=bottom } @@ -3654,7 +3654,7 @@ PresShell :: IsDragInProgress ( ) const } // IsDragInProgress nsIScrollableView* -PresShell::GetViewToScroll() +PresShell::GetViewToScroll(nsLayoutUtils::Direction aDirection) { nsCOMPtr esm = mPresContext->EventStateManager(); nsIScrollableView* scrollView = nsnull; @@ -3670,7 +3670,8 @@ PresShell::GetViewToScroll() } else { nsIView* startView = startFrame->GetClosestView(); if (startView) - scrollView = nsLayoutUtils::GetNearestScrollingView(startView); + scrollView = + nsLayoutUtils::GetNearestScrollingView(startView, aDirection); } } } diff --git a/layout/base/public/nsLayoutUtils.h b/layout/base/public/nsLayoutUtils.h index 5e1cc200d7e2..5e305ba623c6 100644 --- a/layout/base/public/nsLayoutUtils.h +++ b/layout/base/public/nsLayoutUtils.h @@ -164,14 +164,23 @@ public: static PRBool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame, nsIFrame* aCommonAncestor = nsnull); + static nsPresContext::ScrollbarStyles + ScrollbarStylesOfView(nsIScrollableView *aScrollableView); + /** * GetNearestScrollingView locates the first ancestor of aView (or - * aView itself) that is scrollable. + * aView itself) that is scrollable. It does *not* count an + * 'overflow' style of 'hidden' as scrollable, even though a scrolling + * view is present. Thus, the direction of the scroll is needed as + * an argument. * * @param aView the view we're looking at + * @param aDirection Whether it's for horizontal or vertical scrolling. * @return the nearest scrollable view or nsnull if not found */ - static nsIScrollableView* GetNearestScrollingView(nsIView* aView); + enum Direction { eHorizontal, eVertical, eEither }; + static nsIScrollableView* GetNearestScrollingView(nsIView* aView, + Direction aDirection); /** * HasPseudoStyle returns PR_TRUE if aContent (whose primary style diff --git a/layout/base/src/nsLayoutUtils.cpp b/layout/base/src/nsLayoutUtils.cpp index 69e449d78f86..6989da12f5dd 100644 --- a/layout/base/src/nsLayoutUtils.cpp +++ b/layout/base/src/nsLayoutUtils.cpp @@ -46,6 +46,7 @@ #include "nsIView.h" #include "nsIScrollableView.h" #include "nsPlaceholderFrame.h" +#include "nsIScrollableFrame.h" /** * A namespace class for static layout utilities. @@ -348,16 +349,43 @@ nsLayoutUtils::FindSiblingViewFor(nsIView* aParentView, nsIFrame* aFrame) { return nsnull; } +//static +nsPresContext::ScrollbarStyles +nsLayoutUtils::ScrollbarStylesOfView(nsIScrollableView *aScrollableView) +{ + nsIView *view; + CallQueryInterface(aScrollableView, &view); + nsIFrame *frame = NS_STATIC_CAST(nsIFrame*, view->GetClientData()); + if (frame && ((frame = frame->GetParent()))) { + nsIScrollableFrame *sf; + CallQueryInterface(frame, &sf); + if (sf) + return sf->GetScrollbarStyles(); + } + return nsPresContext::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, + NS_STYLE_OVERFLOW_HIDDEN); +} + // static nsIScrollableView* -nsLayoutUtils::GetNearestScrollingView(nsIView* aView) +nsLayoutUtils::GetNearestScrollingView(nsIView* aView, Direction aDirection) { + // Find the first view that has a scrollable frame whose + // ScrollbarStyles is not NS_STYLE_OVERFLOW_HIDDEN in aDirection. NS_ASSERTION(aView, "GetNearestScrollingView expects a non-null view"); nsIScrollableView* scrollableView = nsnull; for (; aView; aView = aView->GetParent()) { CallQueryInterface(aView, &scrollableView); if (scrollableView) { - break; + nsPresContext::ScrollbarStyles ss = + nsLayoutUtils::ScrollbarStylesOfView(scrollableView); + // aDirection can be eHorizontal, eVertical, or eEither + if (aDirection != eHorizontal && + ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) + break; + if (aDirection != eVertical && + ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) + break; } } return scrollableView; diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index b154d9f4e70a..73bc5388e4ff 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -5243,7 +5243,8 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * // Get aView's scrollable view. // - nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView *scrollableView = + nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eEither); if (!scrollableView) return NS_OK; // Nothing to do! @@ -5287,25 +5288,33 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * // nscoord dx = 0, dy = 0; - nsPoint ePoint = aPoint; - ePoint.x += viewOffset.x; - ePoint.y += viewOffset.y; + nsPresContext::ScrollbarStyles ss = + nsLayoutUtils::ScrollbarStylesOfView(scrollableView); + + if (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) { + nscoord e = aPoint.x + viewOffset.x; - nscoord x1 = bounds.x; - nscoord x2 = bounds.x + bounds.width; - nscoord y1 = bounds.y; - nscoord y2 = bounds.y + bounds.height; + nscoord x1 = bounds.x; + nscoord x2 = bounds.x + bounds.width; - if (ePoint.x < x1) - dx = ePoint.x - x1; - else if (ePoint.x > x2) - dx = ePoint.x - x2; - - if (ePoint.y < y1) - dy = ePoint.y - y1; - else if (ePoint.y > y2) - dy = ePoint.y - y2; + if (e < x1) + dx = e - x1; + else if (e > x2) + dx = e - x2; + } + + if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) { + nscoord e = aPoint.y + viewOffset.y; + + nscoord y1 = bounds.y; + nscoord y2 = bounds.y + bounds.height; + + if (e < y1) + dy = e - y1; + else if (e > y2) + dy = e - y2; + } // // Now clip the scroll amounts so that we don't scroll @@ -5326,7 +5335,7 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * dx = 0; else if (dx > 0) { - x1 = scrollX + dx + bounds.width; + nscoord x1 = scrollX + dx + bounds.width; if (x1 > docWidth) dx -= x1 - docWidth; @@ -5337,7 +5346,7 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView * dy = 0; else if (dy > 0) { - y1 = scrollY + dy + bounds.height; + nscoord y1 = scrollY + dy + bounds.height; if (y1 > docHeight) dy -= y1 - docHeight; @@ -5420,7 +5429,8 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie // Find aView's parent scrollable view. // - nsIScrollableView *scrollableView = nsLayoutUtils::GetNearestScrollingView(aView); + nsIScrollableView *scrollableView = + nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eEither); if (scrollableView) { @@ -5442,7 +5452,9 @@ nsTypedSelection::ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aVie while (view) { - scrollableView = nsLayoutUtils::GetNearestScrollingView(view); + scrollableView = + nsLayoutUtils::GetNearestScrollingView(view, + nsLayoutUtils::eEither); if (!scrollableView) break; @@ -6886,7 +6898,8 @@ nsTypedSelection::GetSelectionRegionRectAndScrollableView(SelectionRegion aRegio nsIView* view = parentWithView->GetView(); - *aScrollableView = nsLayoutUtils::GetNearestScrollingView(view); + *aScrollableView = + nsLayoutUtils::GetNearestScrollingView(view, nsLayoutUtils::eEither); if (!*aScrollableView) return NS_OK; @@ -7049,47 +7062,54 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView, nscoord scrollOffsetX = visibleRect.x; nscoord scrollOffsetY = visibleRect.y; + nsPresContext::ScrollbarStyles ss = + nsLayoutUtils::ScrollbarStylesOfView(aScrollableView); + // See how aRect should be positioned vertically - if (NS_PRESSHELL_SCROLL_ANYWHERE == aVPercent) { - // The caller doesn't care where aRect is positioned vertically, - // so long as it's fully visible - if (aRect.y < visibleRect.y) { - // Scroll up so aRect's top edge is visible - scrollOffsetY = aRect.y; - } else if (aRect.YMost() > visibleRect.YMost()) { - // Scroll down so aRect's bottom edge is visible. Make sure - // aRect's top edge is still visible - scrollOffsetY += aRect.YMost() - visibleRect.YMost(); - if (scrollOffsetY > aRect.y) { + if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) { + if (NS_PRESSHELL_SCROLL_ANYWHERE == aVPercent) { + // The caller doesn't care where aRect is positioned vertically, + // so long as it's fully visible + if (aRect.y < visibleRect.y) { + // Scroll up so aRect's top edge is visible scrollOffsetY = aRect.y; + } else if (aRect.YMost() > visibleRect.YMost()) { + // Scroll down so aRect's bottom edge is visible. Make sure + // aRect's top edge is still visible + scrollOffsetY += aRect.YMost() - visibleRect.YMost(); + if (scrollOffsetY > aRect.y) { + scrollOffsetY = aRect.y; + } } + } else { + // Align the aRect edge according to the specified percentage + nscoord frameAlignY = aRect.y + (aRect.height * aVPercent) / 100; + scrollOffsetY = frameAlignY - (visibleRect.height * aVPercent) / 100; } - } else { - // Align the aRect edge according to the specified percentage - nscoord frameAlignY = aRect.y + (aRect.height * aVPercent) / 100; - scrollOffsetY = frameAlignY - (visibleRect.height * aVPercent) / 100; } // See how the aRect should be positioned horizontally - if (NS_PRESSHELL_SCROLL_ANYWHERE == aHPercent) { - // The caller doesn't care where the aRect is positioned horizontally, - // so long as it's fully visible - if (aRect.x < visibleRect.x) { - // Scroll left so the aRect's left edge is visible - scrollOffsetX = aRect.x; - } else if (aRect.XMost() > visibleRect.XMost()) { - // Scroll right so the aRect's right edge is visible. Make sure the - // aRect's left edge is still visible - scrollOffsetX += aRect.XMost() - visibleRect.XMost(); - if (scrollOffsetX > aRect.x) { + if (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) { + if (NS_PRESSHELL_SCROLL_ANYWHERE == aHPercent) { + // The caller doesn't care where the aRect is positioned horizontally, + // so long as it's fully visible + if (aRect.x < visibleRect.x) { + // Scroll left so the aRect's left edge is visible scrollOffsetX = aRect.x; + } else if (aRect.XMost() > visibleRect.XMost()) { + // Scroll right so the aRect's right edge is visible. Make sure the + // aRect's left edge is still visible + scrollOffsetX += aRect.XMost() - visibleRect.XMost(); + if (scrollOffsetX > aRect.x) { + scrollOffsetX = aRect.x; + } } + + } else { + // Align the aRect edge according to the specified percentage + nscoord frameAlignX = aRect.x + (aRect.width * aHPercent) / 100; + scrollOffsetX = frameAlignX - (visibleRect.width * aHPercent) / 100; } - - } else { - // Align the aRect edge according to the specified percentage - nscoord frameAlignX = aRect.x + (aRect.width * aHPercent) / 100; - scrollOffsetX = frameAlignX - (visibleRect.width * aHPercent) / 100; } aScrollableView->ScrollTo(scrollOffsetX, scrollOffsetY, NS_VMREFRESH_IMMEDIATE); @@ -7118,7 +7138,8 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView, if (view) { - nsIScrollableView *parentSV = nsLayoutUtils::GetNearestScrollingView(view); + nsIScrollableView *parentSV = + nsLayoutUtils::GetNearestScrollingView(view, nsLayoutUtils::eEither); if (parentSV) { diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 7de231409ea0..e29fbcd92902 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -1351,7 +1351,7 @@ protected: PRBool IsDragInProgress ( ) const ; // Utility to find which view to scroll. - nsIScrollableView* GetViewToScroll(); + nsIScrollableView* GetViewToScroll(nsLayoutUtils::Direction aDirection); PRBool mCaretEnabled; #ifdef IBMBIDI @@ -3138,7 +3138,7 @@ PresShell::PageMove(PRBool aForward, PRBool aExtend) NS_IMETHODIMP PresShell::ScrollPage(PRBool aForward) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical); if (scrollView) { scrollView->ScrollByPages(0, aForward ? 1 : -1); } @@ -3148,7 +3148,7 @@ PresShell::ScrollPage(PRBool aForward) NS_IMETHODIMP PresShell::ScrollLine(PRBool aForward) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical); if (scrollView) { #ifdef MOZ_WIDGET_COCOA // Emulate the Mac IE behavior of scrolling a minimum of 2 lines @@ -3175,7 +3175,7 @@ PresShell::ScrollLine(PRBool aForward) NS_IMETHODIMP PresShell::ScrollHorizontal(PRBool aLeft) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eHorizontal); if (scrollView) { scrollView->ScrollByLines(aLeft ? -1 : 1, 0); //NEW FOR LINES @@ -3195,7 +3195,7 @@ PresShell::ScrollHorizontal(PRBool aLeft) NS_IMETHODIMP PresShell::CompleteScroll(PRBool aForward) { - nsIScrollableView* scrollView = GetViewToScroll(); + nsIScrollableView* scrollView = GetViewToScroll(nsLayoutUtils::eVertical); if (scrollView) { scrollView->ScrollByWhole(!aForward);//TRUE = top, aForward TRUE=bottom } @@ -3654,7 +3654,7 @@ PresShell :: IsDragInProgress ( ) const } // IsDragInProgress nsIScrollableView* -PresShell::GetViewToScroll() +PresShell::GetViewToScroll(nsLayoutUtils::Direction aDirection) { nsCOMPtr esm = mPresContext->EventStateManager(); nsIScrollableView* scrollView = nsnull; @@ -3670,7 +3670,8 @@ PresShell::GetViewToScroll() } else { nsIView* startView = startFrame->GetClosestView(); if (startView) - scrollView = nsLayoutUtils::GetNearestScrollingView(startView); + scrollView = + nsLayoutUtils::GetNearestScrollingView(startView, aDirection); } } }