From 01f49c7c7b44ea9eba288d95be9a5f1f12ef6bd6 Mon Sep 17 00:00:00 2001 From: Oleg Romashin Date: Tue, 7 Feb 2012 12:24:15 -0800 Subject: [PATCH] Bug 681192. Part 5: Make various DOM scroll APIs --- scrollTop, scrollLeft, window.scrollTo, scrollBox.scrollTo, scrollBox.scrollToLine, scrollBox.scrollBy --- use an appropriate allowed scroll destination range. r=roc,r=matspal --HG-- extra : rebase_source : 83ee44530c67229686ec0dce3628da83e0e93438 --- content/base/src/nsGenericElement.cpp | 10 ++++-- dom/base/nsGlobalWindow.cpp | 9 ++++-- layout/xul/base/src/nsScrollBoxObject.cpp | 38 +++++++++++++++++------ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index e3b29133cd3..f60ed069065 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -2142,7 +2142,10 @@ nsGenericElement::SetScrollTop(PRInt32 aScrollTop) if (sf) { nsPoint pt = sf->GetScrollPosition(); pt.y = nsPresContext::CSSPixelsToAppUnits(aScrollTop); - sf->ScrollTo(pt, nsIScrollableFrame::INSTANT); + nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f); + // Don't allow pt.y + halfPixel since that would round up to the next CSS pixel. + nsRect range(pt.x, pt.y - halfPixel, 0, halfPixel*2 - 1); + sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range); } return NS_OK; } @@ -2172,7 +2175,10 @@ nsGenericElement::SetScrollLeft(PRInt32 aScrollLeft) if (sf) { nsPoint pt = sf->GetScrollPosition(); pt.x = nsPresContext::CSSPixelsToAppUnits(aScrollLeft); - sf->ScrollTo(pt, nsIScrollableFrame::INSTANT); + nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f); + // Don't allow pt.x + halfPixel since that would round up to the next CSS pixel. + nsRect range(pt.x - halfPixel, pt.y, halfPixel*2 - 1, 0); + sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range); } return NS_OK; } diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index b3c5bc0373e..118bdb04579 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -5329,9 +5329,12 @@ nsGlobalWindow::ScrollTo(PRInt32 aXScroll, PRInt32 aYScroll) if (aYScroll > maxpx) { aYScroll = maxpx; } - sf->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aXScroll), - nsPresContext::CSSPixelsToAppUnits(aYScroll)), - nsIScrollableFrame::INSTANT); + nsPoint pt(nsPresContext::CSSPixelsToAppUnits(aXScroll), + nsPresContext::CSSPixelsToAppUnits(aYScroll)); + nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f); + // Don't allow pt.x/y + halfPixel since that would round up to the next CSS pixel. + nsRect range(pt.x - halfPixel, pt.y - halfPixel, halfPixel*2 - 1, halfPixel*2 - 1); + sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range); } return NS_OK; diff --git a/layout/xul/base/src/nsScrollBoxObject.cpp b/layout/xul/base/src/nsScrollBoxObject.cpp index 847f75e351d..420f2465b8f 100644 --- a/layout/xul/base/src/nsScrollBoxObject.cpp +++ b/layout/xul/base/src/nsScrollBoxObject.cpp @@ -91,9 +91,12 @@ NS_IMETHODIMP nsScrollBoxObject::ScrollTo(PRInt32 x, PRInt32 y) if (!sf) return NS_ERROR_FAILURE; - sf->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(x), - nsPresContext::CSSPixelsToAppUnits(y)), - nsIScrollableFrame::INSTANT); + nsPoint pt(nsPresContext::CSSPixelsToAppUnits(x), + nsPresContext::CSSPixelsToAppUnits(y)); + nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f); + // Don't allow pt.x/y + halfPixel since that would round up to the next CSS pixel. + nsRect range(pt.x - halfPixel, pt.y - halfPixel, halfPixel*2 - 1, halfPixel*2 - 1); + sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range); return NS_OK; } @@ -225,16 +228,29 @@ NS_IMETHODIMP nsScrollBoxObject::ScrollByIndex(PRInt32 dindexes) } } - if (horiz) + nscoord csspixel = nsPresContext::CSSPixelsToAppUnits(1); + if (horiz) { // In the left-to-right case we scroll so that the left edge of the // selected child is scrolled to the left edge of the scrollbox. // In the right-to-left case we scroll so that the right edge of the // selected child is scrolled to the right edge of the scrollbox. - sf->ScrollTo(nsPoint(isLTR ? rect.x : rect.x + rect.width - frameWidth, - cp.y), - nsIScrollableFrame::INSTANT); - else - sf->ScrollTo(nsPoint(cp.x, rect.y), nsIScrollableFrame::INSTANT); + + nsPoint pt(isLTR ? rect.x : rect.x + rect.width - frameWidth, + cp.y); + + // Use a destination range that ensures the left edge (or right edge, + // for RTL) will indeed be visible. Also ensure that the top edge + // is visible. + nsRect range(pt.x, pt.y, csspixel, 0); + if (isLTR) { + range.x -= csspixel; + } + sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range); + } else { + // Use a destination range that ensures the top edge will be visible. + nsRect range(cp.x, rect.y - csspixel, 0, csspixel); + sf->ScrollTo(nsPoint(cp.x, rect.y), nsIScrollableFrame::INSTANT, &range); + } return NS_OK; } @@ -247,7 +263,9 @@ NS_IMETHODIMP nsScrollBoxObject::ScrollToLine(PRInt32 line) return NS_ERROR_FAILURE; nscoord y = sf->GetLineScrollAmount().height * line; - sf->ScrollTo(nsPoint(0, y), nsIScrollableFrame::INSTANT); + nsRect range(0, y - nsPresContext::CSSPixelsToAppUnits(1), + 0, nsPresContext::CSSPixelsToAppUnits(1)); + sf->ScrollTo(nsPoint(0, y), nsIScrollableFrame::INSTANT, &range); return NS_OK; }