| Index: Source/platform/scroll/ScrollView.cpp
|
| diff --git a/Source/platform/scroll/ScrollView.cpp b/Source/platform/scroll/ScrollView.cpp
|
| index 12c7d974106dbb2fff98c5776cc851f42525dcfc..dfd92f7a01731c24c3955e0110b0c0150427bf79 100644
|
| --- a/Source/platform/scroll/ScrollView.cpp
|
| +++ b/Source/platform/scroll/ScrollView.cpp
|
| @@ -31,6 +31,7 @@
|
| #include "platform/HostWindow.h"
|
| #include "platform/scroll/ScrollbarTheme.h"
|
| #include "wtf/StdLibExtras.h"
|
| +#include "wtf/TemporaryChange.h"
|
|
|
| using namespace std;
|
|
|
| @@ -44,7 +45,6 @@ ScrollView::ScrollView()
|
| , m_scrollbarsAvoidingResizer(0)
|
| , m_scrollbarsSuppressed(false)
|
| , m_inUpdateScrollbars(false)
|
| - , m_updateScrollbarsPass(0)
|
| , m_drawPanScrollIcon(false)
|
| , m_paintsEntireContents(false)
|
| , m_clipsRepaints(true)
|
| @@ -324,29 +324,19 @@ void ScrollView::windowResizerRectChanged()
|
| updateScrollbars(scrollOffset());
|
| }
|
|
|
| -static const unsigned cMaxUpdateScrollbarsPass = 2;
|
| -
|
| -void ScrollView::updateScrollbars(const IntSize& desiredOffset)
|
| +static bool useOverlayScrollbars()
|
| {
|
| - if (m_inUpdateScrollbars)
|
| - return;
|
| -
|
| - // If we came in here with the view already needing a layout, then go ahead and do that
|
| - // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
|
| - // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
|
| - if (!m_scrollbarsSuppressed) {
|
| - m_inUpdateScrollbars = true;
|
| - scrollbarExistenceDidChange();
|
| - m_inUpdateScrollbars = false;
|
| - }
|
| -
|
| - IntRect oldScrollCornerRect = scrollCornerRect();
|
| + // FIXME: Need to detect the presence of CSS custom scrollbars, which are non-overlay regardless the ScrollbarTheme.
|
| + return ScrollbarTheme::theme()->usesOverlayScrollbars();
|
| +}
|
|
|
| +void ScrollView::computeScrollbarExistence(bool& newHasHorizontalScrollbar, bool& newHasVerticalScrollbar, ComputeScrollbarExistenceOption option) const
|
| +{
|
| bool hasHorizontalScrollbar = m_horizontalScrollbar;
|
| bool hasVerticalScrollbar = m_verticalScrollbar;
|
|
|
| - bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
|
| - bool newHasVerticalScrollbar = hasVerticalScrollbar;
|
| + newHasHorizontalScrollbar = hasHorizontalScrollbar;
|
| + newHasVerticalScrollbar = hasVerticalScrollbar;
|
|
|
| ScrollbarMode hScroll = m_horizontalScrollbarMode;
|
| ScrollbarMode vScroll = m_verticalScrollbarMode;
|
| @@ -356,86 +346,40 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
|
| if (vScroll != ScrollbarAuto)
|
| newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
|
|
|
| - if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
|
| - if (hasHorizontalScrollbar != newHasHorizontalScrollbar)
|
| - setHasHorizontalScrollbar(newHasHorizontalScrollbar);
|
| - if (hasVerticalScrollbar != newHasVerticalScrollbar)
|
| - setHasVerticalScrollbar(newHasVerticalScrollbar);
|
| - } else {
|
| - bool scrollbarExistenceChanged = false;
|
| -
|
| - IntSize docSize = contentsSize();
|
| - IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
|
| + if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto))
|
| + return;
|
|
|
| - bool scrollbarsAreOverlay = ScrollbarTheme::theme()->usesOverlayScrollbars();
|
| + IntSize docSize = contentsSize();
|
|
|
| - if (hScroll == ScrollbarAuto) {
|
| - newHasHorizontalScrollbar = docSize.width() > visibleWidth();
|
| - if (!scrollbarsAreOverlay && newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
|
| - newHasHorizontalScrollbar = false;
|
| - }
|
| - if (vScroll == ScrollbarAuto) {
|
| - newHasVerticalScrollbar = docSize.height() > visibleHeight();
|
| - if (!scrollbarsAreOverlay && newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height())
|
| - newHasVerticalScrollbar = false;
|
| - }
|
| + if (hScroll == ScrollbarAuto)
|
| + newHasHorizontalScrollbar = docSize.width() > visibleWidth();
|
| + if (vScroll == ScrollbarAuto)
|
| + newHasVerticalScrollbar = docSize.height() > visibleHeight();
|
|
|
| - if (!scrollbarsAreOverlay) {
|
| - // If we ever turn one scrollbar off, always turn the other one off too. Never ever
|
| - // try to both gain/lose a scrollbar in the same pass.
|
| - if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
|
| - newHasVerticalScrollbar = false;
|
| - if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
|
| - newHasHorizontalScrollbar = false;
|
| - }
|
| -
|
| - if (hasHorizontalScrollbar != newHasHorizontalScrollbar) {
|
| - scrollbarExistenceChanged = true;
|
| - if (scrollOrigin().y() && !newHasHorizontalScrollbar && !scrollbarsAreOverlay)
|
| - ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x(), scrollOrigin().y() - m_horizontalScrollbar->height()));
|
| - if (hasHorizontalScrollbar)
|
| - m_horizontalScrollbar->invalidate();
|
| - setHasHorizontalScrollbar(newHasHorizontalScrollbar);
|
| - }
|
| + if (useOverlayScrollbars())
|
| + return;
|
|
|
| - if (hasVerticalScrollbar != newHasVerticalScrollbar) {
|
| - scrollbarExistenceChanged = true;
|
| - if (scrollOrigin().x() && !newHasVerticalScrollbar && !scrollbarsAreOverlay)
|
| - ScrollableArea::setScrollOrigin(IntPoint(scrollOrigin().x() - m_verticalScrollbar->width(), scrollOrigin().y()));
|
| - if (hasVerticalScrollbar)
|
| - m_verticalScrollbar->invalidate();
|
| - setHasVerticalScrollbar(newHasVerticalScrollbar);
|
| - }
|
| + IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
|
|
|
| - if (scrollbarExistenceChanged) {
|
| - if (scrollbarsAreOverlay) {
|
| - // Synchronize status of scrollbar layers if necessary.
|
| - m_inUpdateScrollbars = true;
|
| - scrollbarExistenceDidChange();
|
| - m_inUpdateScrollbars = false;
|
| - } else if (m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
|
| - m_updateScrollbarsPass++;
|
| - contentsResized();
|
| - scrollbarExistenceDidChange();
|
| - IntSize newDocSize = contentsSize();
|
| - if (newDocSize == docSize) {
|
| - // The layout with the new scroll state had no impact on
|
| - // the document's overall size, so updateScrollbars didn't get called.
|
| - // Recur manually.
|
| - updateScrollbars(desiredOffset);
|
| - }
|
| - m_updateScrollbarsPass--;
|
| - }
|
| - }
|
| + bool attemptToRemoveScrollbars = (option == FirstPass
|
| + && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height());
|
| + if (attemptToRemoveScrollbars) {
|
| + if (hScroll == ScrollbarAuto)
|
| + newHasHorizontalScrollbar = false;
|
| + if (vScroll == ScrollbarAuto)
|
| + newHasVerticalScrollbar = false;
|
| }
|
|
|
| - // Set up the range, but only do this if we're not in a nested call (to avoid
|
| - // doing it multiple times).
|
| - if (m_updateScrollbarsPass)
|
| - return;
|
| -
|
| - m_inUpdateScrollbars = true;
|
| + // If we ever turn one scrollbar off, always turn the other one off too.
|
| + // Never ever try to both gain/lose a scrollbar in the same pass.
|
| + if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
|
| + newHasVerticalScrollbar = false;
|
| + if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
|
| + newHasHorizontalScrollbar = false;
|
| +}
|
|
|
| +void ScrollView::updateScrollbarGeometry()
|
| +{
|
| if (m_horizontalScrollbar) {
|
| int clientWidth = visibleWidth();
|
| IntRect oldRect(m_horizontalScrollbar->frameRect());
|
| @@ -451,6 +395,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
|
| m_horizontalScrollbar->setSuppressInvalidation(true);
|
| m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
|
| m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
|
| + m_horizontalScrollbar->offsetDidChange();
|
| if (m_scrollbarsSuppressed)
|
| m_horizontalScrollbar->setSuppressInvalidation(false);
|
| }
|
| @@ -470,35 +415,88 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
|
| m_verticalScrollbar->setSuppressInvalidation(true);
|
| m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight);
|
| m_verticalScrollbar->setProportion(clientHeight, contentsHeight());
|
| + m_verticalScrollbar->offsetDidChange();
|
| if (m_scrollbarsSuppressed)
|
| m_verticalScrollbar->setSuppressInvalidation(false);
|
| }
|
| +}
|
| +
|
| +bool ScrollView::adjustScrollbarExistence(ComputeScrollbarExistenceOption option)
|
| +{
|
| + ASSERT(m_inUpdateScrollbars);
|
|
|
| - if (hasHorizontalScrollbar != newHasHorizontalScrollbar || hasVerticalScrollbar != newHasVerticalScrollbar) {
|
| + // If we came in here with the view already needing a layout, then go ahead and do that
|
| + // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
|
| + // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
|
| + if (!m_scrollbarsSuppressed)
|
| + scrollbarExistenceDidChange();
|
| +
|
| + bool hasHorizontalScrollbar = m_horizontalScrollbar;
|
| + bool hasVerticalScrollbar = m_verticalScrollbar;
|
| +
|
| + bool newHasHorizontalScrollbar = false;
|
| + bool newHasVerticalScrollbar = false;
|
| + computeScrollbarExistence(newHasHorizontalScrollbar, newHasVerticalScrollbar, option);
|
| +
|
| + bool scrollbarExistenceChanged = hasHorizontalScrollbar != newHasHorizontalScrollbar || hasVerticalScrollbar != newHasVerticalScrollbar;
|
| + if (!scrollbarExistenceChanged)
|
| + return false;
|
| +
|
| + setHasHorizontalScrollbar(newHasHorizontalScrollbar);
|
| + setHasVerticalScrollbar(newHasVerticalScrollbar);
|
| +
|
| + if (m_scrollbarsSuppressed)
|
| + return true;
|
| +
|
| + if (!useOverlayScrollbars())
|
| + contentsResized();
|
| + scrollbarExistenceDidChange();
|
| + return true;
|
| +}
|
| +
|
| +void ScrollView::updateScrollbars(const IntSize& desiredOffset)
|
| +{
|
| + if (m_inUpdateScrollbars)
|
| + return;
|
| + TemporaryChange<bool> inUpdateScrollbarsChange(m_inUpdateScrollbars, true);
|
| +
|
| + IntSize oldVisibleSize = visibleSize();
|
| +
|
| + bool scrollbarExistenceChanged = false;
|
| + int maxUpdateScrollbarsPass = useOverlayScrollbars() || m_scrollbarsSuppressed ? 1 : 3;
|
| + for (int updateScrollbarsPass = 0; updateScrollbarsPass < maxUpdateScrollbarsPass; updateScrollbarsPass++) {
|
| + if (!adjustScrollbarExistence(updateScrollbarsPass ? Incremental : FirstPass))
|
| + break;
|
| + scrollbarExistenceChanged = true;
|
| + }
|
| +
|
| + updateScrollbarGeometry();
|
| +
|
| + if (scrollbarExistenceChanged) {
|
| // FIXME: Is frameRectsChanged really necessary here? Have any frame rects changed?
|
| frameRectsChanged();
|
| positionScrollbarLayers();
|
| updateScrollCorner();
|
| - if (!m_horizontalScrollbar && !m_verticalScrollbar)
|
| - invalidateScrollCornerRect(oldScrollCornerRect);
|
| }
|
|
|
| + // FIXME: We don't need to do this if we are composited.
|
| + IntSize newVisibleSize = visibleSize();
|
| + if (newVisibleSize.width() > oldVisibleSize.width()) {
|
| + if (shouldPlaceVerticalScrollbarOnLeft())
|
| + invalidateRect(IntRect(0, 0, newVisibleSize.width() - oldVisibleSize.width(), newVisibleSize.height()));
|
| + else
|
| + invalidateRect(IntRect(oldVisibleSize.width(), 0, newVisibleSize.width() - oldVisibleSize.width(), newVisibleSize.height()));
|
| + }
|
| + if (newVisibleSize.height() > oldVisibleSize.height())
|
| + invalidateRect(IntRect(0, oldVisibleSize.height(), newVisibleSize.width(), newVisibleSize.height() - oldVisibleSize.height()));
|
| +
|
| IntPoint adjustedScrollPosition = IntPoint(desiredOffset);
|
| if (!isRubberBandInProgress())
|
| adjustedScrollPosition = adjustScrollPositionWithinRange(adjustedScrollPosition);
|
| -
|
| if (adjustedScrollPosition != scrollPosition() || scrollOriginChanged()) {
|
| ScrollableArea::scrollToOffsetWithoutAnimation(adjustedScrollPosition);
|
| resetScrollOriginChanged();
|
| }
|
| -
|
| - // Make sure the scrollbar offsets are up to date.
|
| - if (m_horizontalScrollbar)
|
| - m_horizontalScrollbar->offsetDidChange();
|
| - if (m_verticalScrollbar)
|
| - m_verticalScrollbar->offsetDidChange();
|
| -
|
| - m_inUpdateScrollbars = false;
|
| }
|
|
|
| const int panIconSizeLength = 16;
|
|
|