⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scrollview.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#include "config.h"#include "ScrollView.h"#include "GraphicsContext.h"#include "HostWindow.h"#include "PlatformMouseEvent.h"#include "PlatformWheelEvent.h"#include "Scrollbar.h"#include "ScrollbarTheme.h"#include <wtf/StdLibExtras.h>using std::max;namespace WebCore {ScrollView::ScrollView()    : m_horizontalScrollbarMode(ScrollbarAuto)    , m_verticalScrollbarMode(ScrollbarAuto)    , m_prohibitsScrolling(false)    , m_canBlitOnScroll(true)    , m_scrollbarsAvoidingResizer(0)    , m_scrollbarsSuppressed(false)    , m_inUpdateScrollbars(false)    , m_drawPanScrollIcon(false)    , m_useFixedLayout(false){    platformInit();}ScrollView::~ScrollView(){    platformDestroy();}void ScrollView::addChild(Widget* child) {    ASSERT(child != this && !child->parent());    child->setParent(this);    m_children.add(child);    if (child->platformWidget())        platformAddChild(child);}void ScrollView::removeChild(Widget* child){    ASSERT(child->parent() == this);    child->setParent(0);    m_children.remove(child);    if (child->platformWidget())        platformRemoveChild(child);}void ScrollView::setHasHorizontalScrollbar(bool hasBar){    if (hasBar && !m_horizontalScrollbar && !platformHasHorizontalAdjustment()) {        m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);        addChild(m_horizontalScrollbar.get());    } else if (!hasBar && m_horizontalScrollbar) {        removeChild(m_horizontalScrollbar.get());        m_horizontalScrollbar = 0;    }}void ScrollView::setHasVerticalScrollbar(bool hasBar){    if (hasBar && !m_verticalScrollbar && !platformHasVerticalAdjustment()) {        m_verticalScrollbar = createScrollbar(VerticalScrollbar);        addChild(m_verticalScrollbar.get());    } else if (!hasBar && m_verticalScrollbar) {        removeChild(m_verticalScrollbar.get());        m_verticalScrollbar = 0;    }}PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation){    return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);}void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode){    if (horizontalMode == horizontalScrollbarMode() && verticalMode == verticalScrollbarMode())        return;    m_horizontalScrollbarMode = horizontalMode;    m_verticalScrollbarMode = verticalMode;    if (platformWidget())        platformSetScrollbarModes();    else        updateScrollbars(scrollOffset());}void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const{    if (platformWidget()) {        platformScrollbarModes(horizontalMode, verticalMode);        return;    }    horizontalMode = m_horizontalScrollbarMode;    verticalMode = m_verticalScrollbarMode;}void ScrollView::setCanHaveScrollbars(bool canScroll){    ScrollbarMode newHorizontalMode;    ScrollbarMode newVerticalMode;        scrollbarModes(newHorizontalMode, newVerticalMode);        if (canScroll && newVerticalMode == ScrollbarAlwaysOff)        newVerticalMode = ScrollbarAuto;    else if (!canScroll)        newVerticalMode = ScrollbarAlwaysOff;        if (canScroll && newHorizontalMode == ScrollbarAlwaysOff)        newHorizontalMode = ScrollbarAuto;    else if (!canScroll)        newHorizontalMode = ScrollbarAlwaysOff;        setScrollbarModes(newHorizontalMode, newVerticalMode);}void ScrollView::setCanBlitOnScroll(bool b){    if (platformWidget()) {        platformSetCanBlitOnScroll(b);        return;    }    m_canBlitOnScroll = b;}bool ScrollView::canBlitOnScroll() const{    if (platformWidget())        return platformCanBlitOnScroll();    return m_canBlitOnScroll;}IntRect ScrollView::visibleContentRect(bool includeScrollbars) const{    if (platformWidget())        return platformVisibleContentRect(includeScrollbars);    return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),                   IntSize(max(0, width() - (verticalScrollbar() && !includeScrollbars ? verticalScrollbar()->width() : 0)),                            max(0, height() - (horizontalScrollbar() && !includeScrollbars ? horizontalScrollbar()->height() : 0))));}int ScrollView::layoutWidth() const{    return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleWidth() : m_fixedLayoutSize.width();}int ScrollView::layoutHeight() const{    return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleHeight() : m_fixedLayoutSize.height();}IntSize ScrollView::fixedLayoutSize() const{    return m_fixedLayoutSize;}void ScrollView::setFixedLayoutSize(const IntSize& newSize){    if (fixedLayoutSize() == newSize)        return;    m_fixedLayoutSize = newSize;    updateScrollbars(scrollOffset());}bool ScrollView::useFixedLayout() const{    return m_useFixedLayout;}void ScrollView::setUseFixedLayout(bool enable){    if (useFixedLayout() == enable)        return;    m_useFixedLayout = enable;    updateScrollbars(scrollOffset());}IntSize ScrollView::contentsSize() const{    if (platformWidget())        return platformContentsSize();    return m_contentsSize;}void ScrollView::setContentsSize(const IntSize& newSize){    if (contentsSize() == newSize)        return;    m_contentsSize = newSize;    if (platformWidget())        platformSetContentsSize();    else        updateScrollbars(scrollOffset());}IntPoint ScrollView::maximumScrollPosition() const{    IntSize maximumOffset = contentsSize() - visibleContentRect().size();    maximumOffset.clampNegativeToZero();    return IntPoint(maximumOffset.width(), maximumOffset.height());}void ScrollView::valueChanged(Scrollbar* scrollbar){    // Figure out if we really moved.    IntSize newOffset = m_scrollOffset;    if (scrollbar) {        if (scrollbar == m_horizontalScrollbar)            newOffset.setWidth(scrollbar->value());        else if (scrollbar == m_verticalScrollbar)            newOffset.setHeight(scrollbar->value());    }    IntSize scrollDelta = newOffset - m_scrollOffset;    if (scrollDelta == IntSize())        return;    m_scrollOffset = newOffset;    if (scrollbarsSuppressed())        return;    scrollContents(scrollDelta);}void ScrollView::scrollRectIntoViewRecursively(const IntRect& r){    // FIXME: This method is not transform-aware.  It should just be moved to FrameView so that an accurate    // position for the child view can be determined.    IntRect rect = r;    ScrollView* view = this;    while (view) {        if (view->prohibitsScrolling()) // Allow the views to scroll into view recursively until we hit one that prohibits scrolling.            return;        view->setScrollPosition(rect.location());        rect.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());        if (view->parent())            rect.intersect(view->frameRect());        view = view->parent();    }        // We may be embedded inside some containing platform scroll view that we don't manage.  This is the case    // in Mail.app on OS X, for example, where the WebKit view for message bodies is inside a Cocoa NSScrollView    // that contains both it and message headers.  Let the HostWindow know about this scroll so that it can pass the message    // on up the view chain.    // This rect is not clamped, since Mail actually relies on receiving an unclamped rect with negative coordinates in order to    // expose the headers.    hostWindow()->scrollRectIntoView(rect, this);}void ScrollView::setScrollPosition(const IntPoint& scrollPoint){    if (prohibitsScrolling())        return;    if (platformWidget()) {        platformSetScrollPosition(scrollPoint);        return;    }    IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition());    newScrollPosition.clampNegativeToZero();    if (newScrollPosition == scrollPosition())        return;    updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y()));}bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity){    if (platformWidget())        return platformScroll(direction, granularity);    if (direction == ScrollUp || direction == ScrollDown) {        if (m_verticalScrollbar)            return m_verticalScrollbar->scroll(direction, granularity);    } else {        if (m_horizontalScrollbar)            return m_horizontalScrollbar->scroll(direction, granularity);    }    return false;}void ScrollView::updateScrollbars(const IntSize& desiredOffset){    // Don't allow re-entrancy into this function.    if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())        return;    m_inUpdateScrollbars = true;    bool hasVerticalScrollbar = m_verticalScrollbar;    bool hasHorizontalScrollbar = m_horizontalScrollbar;    bool oldHasVertical = hasVerticalScrollbar;    bool oldHasHorizontal = hasHorizontalScrollbar;    ScrollbarMode hScroll = m_horizontalScrollbarMode;    ScrollbarMode vScroll = m_verticalScrollbarMode;    const int scrollbarThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();    for (int pass = 0; pass < 2; pass++) {        bool scrollsVertically;        bool scrollsHorizontally;        if (!m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {            // Do a layout if pending before checking if scrollbars are needed.            if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)                visibleContentsResized();            scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());            if (scrollsVertically)                scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + scrollbarThickness > width());            else {                scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());                if (scrollsHorizontally)                    scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + scrollbarThickness > height());            }        } else {            scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);            scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);        }                if (hasVerticalScrollbar != scrollsVertically) {            setHasVerticalScrollbar(scrollsVertically);            hasVerticalScrollbar = scrollsVertically;        }        if (hasHorizontalScrollbar != scrollsHorizontally) {            setHasHorizontalScrollbar(scrollsHorizontally);            hasHorizontalScrollbar = scrollsHorizontally;        }    }        // Set up the range (and page step/line step).    IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());    IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);    scroll.clampNegativeToZero();     if (!platformHandleHorizontalAdjustment(scroll) && m_horizontalScrollbar) {        int clientWidth = visibleWidth();        m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);        int pageStep = (clientWidth - cAmountToKeepWhenPaging);        if (pageStep < 0)            pageStep = clientWidth;        IntRect oldRect(m_horizontalScrollbar->frameRect());        IntRect hBarRect = IntRect(0,                                   height() - m_horizontalScrollbar->height(),                                   width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0),                                   m_horizontalScrollbar->height());        m_horizontalScrollbar->setFrameRect(hBarRect);        if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect())            m_horizontalScrollbar->invalidate();        if (m_scrollbarsSuppressed)            m_horizontalScrollbar->setSuppressInvalidation(true);        m_horizontalScrollbar->setSteps(cScrollbarPixelsPerLineStep, pageStep);        m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());        m_horizontalScrollbar->setValue(scroll.width());        if (m_scrollbarsSuppressed)            m_horizontalScrollbar->setSuppressInvalidation(false);     }     if (!platformHandleVerticalAdjustment(scroll) && m_verticalScrollbar) {        int clientHeight = visibleHeight();        m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight);        int pageStep = (clientHeight - cAmountToKeepWhenPaging);        if (pageStep < 0)            pageStep = clientHeight;        IntRect oldRect(m_verticalScrollbar->frameRect());        IntRect vBarRect = IntRect(width() - m_verticalScrollbar->width(),                                    0,                                   m_verticalScrollbar->width(),                                   height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0));        m_verticalScrollbar->setFrameRect(vBarRect);        if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect())            m_verticalScrollbar->invalidate();        if (m_scrollbarsSuppressed)            m_verticalScrollbar->setSuppressInvalidation(true);        m_verticalScrollbar->setSteps(cScrollbarPixelsPerLineStep, pageStep);        m_verticalScrollbar->setProportion(clientHeight, contentsHeight());        m_verticalScrollbar->setValue(scroll.height());        if (m_scrollbarsSuppressed)            m_verticalScrollbar->setSuppressInvalidation(false);    }    if (oldHasVertical != (m_verticalScrollbar != 0) || oldHasHorizontal != (m_horizontalScrollbar != 0))        frameRectsChanged();    // See if our offset has changed in a situation where we might not have scrollbars.    // This can happen when editing a body with overflow:hidden and scrolling to reveal selection.    // It can also happen when maximizing a window that has scrollbars (but the new maximized result    // does not).    IntSize scrollDelta = scroll - m_scrollOffset;    if (scrollDelta != IntSize()) {       m_scrollOffset = scroll;       scrollContents(scrollDelta);    }    m_inUpdateScrollbars = false;}const int panIconSizeLength = 20;void ScrollView::scrollContents(const IntSize& scrollDelta){    if (!hostWindow())        return;    // Since scrolling is double buffered, we will be blitting the scroll view's intersection    // with the clip rect every time to keep it smooth.    IntRect clipRect = windowClipRect();    IntRect scrollViewRect = convertToContainingWindow(IntRect(0, 0, visibleWidth(), visibleHeight()));    IntRect updateRect = clipRect;    updateRect.intersect(scrollViewRect);    // Invalidate the window (not the backing store).    hostWindow()->repaint(updateRect, false);    if (m_drawPanScrollIcon) {        int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary        IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));        IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation , IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));        panScrollIconDirtyRect.intersect(clipRect);        hostWindow()->repaint(panScrollIconDirtyRect, true);    }    if (canBlitOnScroll() && !rootPreventsBlitting()) { // The main frame can just blit the WebView window       // FIXME: Find a way to blit subframes without blitting overlapping content       hostWindow()->scroll(-scrollDelta, scrollViewRect, clipRect);    } else { 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -