frameview.cpp

来自「linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自Web」· C++ 代码 · 共 1,433 行 · 第 1/3 页

CPP
1,433
字号
/* * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> *                     1999 Lars Knoll <knoll@kde.org> *                     1999 Antti Koivisto <koivisto@kde.org> *                     2000 Dirk Mueller <mueller@kde.org> * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. *           (C) 2006 Graham Dennis (graham.dennis@gmail.com) *           (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */#include "config.h"#include "FrameView.h"#include "AXObjectCache.h"#include "CSSStyleSelector.h"#include "ChromeClient.h"#include "DocLoader.h"#include "EventHandler.h"#include "FloatRect.h"#include "FocusController.h"#include "Frame.h"#include "FrameLoader.h"#include "FrameLoaderClient.h"#include "FrameTree.h"#include "GraphicsContext.h"#include "HTMLDocument.h"#include "HTMLFrameElement.h"#include "HTMLFrameSetElement.h"#include "HTMLNames.h"#include "OverflowEvent.h"#include "Page.h"#include "RenderPart.h"#include "RenderPartObject.h"#include "RenderScrollbar.h"#include "RenderTheme.h"#include "RenderView.h"#include "Settings.h"#include <wtf/CurrentTime.h>#if USE(ACCELERATED_COMPOSITING)#include "RenderLayerCompositor.h"#endifnamespace WebCore {using namespace HTMLNames;double FrameView::sCurrentPaintTimeStamp = 0.0;#if ENABLE(REPAINT_THROTTLING)// Normal delaystatic const double deferredRepaintDelay = 0.025;// Negative value would mean that first few repaints happen without a delaystatic const double initialDeferredRepaintDelayDuringLoading = 0;// The delay grows on each repaint to this maximum valuestatic const double maxDeferredRepaintDelayDuringLoading = 2.5;// On each repaint the delay increses by this amountstatic const double deferredRepaintDelayIncrementDuringLoading = 0.5;#else// FIXME: Repaint throttling could be good to have on all platform.// The balance between CPU use and repaint frequency will need some tuning for desktop.// More hooks may be needed to reset the delay on things like GIF and CSS animations.static const double deferredRepaintDelay = 0;static const double initialDeferredRepaintDelayDuringLoading = 0;static const double maxDeferredRepaintDelayDuringLoading = 0;static const double deferredRepaintDelayIncrementDuringLoading = 0;#endifstruct ScheduledEvent {    RefPtr<Event> m_event;    RefPtr<Node> m_eventTarget;};FrameView::FrameView(Frame* frame)    : m_refCount(1)    , m_frame(frame)    , m_vmode(ScrollbarAuto)    , m_hmode(ScrollbarAuto)    , m_slowRepaintObjectCount(0)    , m_layoutTimer(this, &FrameView::layoutTimerFired)    , m_layoutRoot(0)    , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)    , m_needToInitScrollbars(true)    , m_isTransparent(false)    , m_baseBackgroundColor(Color::white)    , m_mediaType("screen")    , m_enqueueEvents(0)    , m_overflowStatusDirty(true)    , m_viewportRenderer(0)    , m_wasScrolledByUser(false)    , m_inProgrammaticScroll(false)    , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)    , m_shouldUpdateWhileOffscreen(true){    init();    show();}FrameView::FrameView(Frame* frame, const IntSize& initialSize)    : m_refCount(1)    , m_frame(frame)    , m_vmode(ScrollbarAuto)    , m_hmode(ScrollbarAuto)    , m_slowRepaintObjectCount(0)    , m_layoutTimer(this, &FrameView::layoutTimerFired)    , m_layoutRoot(0)    , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)    , m_needToInitScrollbars(true)    , m_isTransparent(false)    , m_baseBackgroundColor(Color::white)    , m_mediaType("screen")    , m_enqueueEvents(0)    , m_overflowStatusDirty(true)    , m_viewportRenderer(0)    , m_wasScrolledByUser(false)    , m_inProgrammaticScroll(false)    , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)    , m_shouldUpdateWhileOffscreen(true){    init();    Widget::setFrameRect(IntRect(x(), y(), initialSize.width(), initialSize.height()));    show();}FrameView::~FrameView(){    if (m_postLayoutTasksTimer.isActive()) {        m_postLayoutTasksTimer.stop();        m_scheduledEvents.clear();        m_enqueueEvents = 0;    }    resetScrollbars();    setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.    setHasVerticalScrollbar(false);        ASSERT(m_refCount == 0);    ASSERT(m_scheduledEvents.isEmpty());    ASSERT(!m_enqueueEvents);    if (m_frame) {        ASSERT(m_frame->view() != this || !m_frame->contentRenderer());        RenderPart* renderer = m_frame->ownerRenderer();        if (renderer && renderer->widget() == this)            renderer->setWidget(0);    }}void FrameView::reset(){    m_useSlowRepaints = false;    m_borderX = 30;    m_borderY = 30;    m_layoutTimer.stop();    m_layoutRoot = 0;    m_delayedLayout = false;    m_doFullRepaint = true;    m_layoutSchedulingEnabled = true;    m_midLayout = false;    m_layoutCount = 0;    m_nestedLayoutCount = 0;    m_postLayoutTasksTimer.stop();    m_firstLayout = true;    m_firstLayoutCallbackPending = false;    m_wasScrolledByUser = false;    m_lastLayoutSize = IntSize();    m_lastZoomFactor = 1.0f;    m_deferringRepaints = 0;    m_repaintCount = 0;    m_repaintRects.clear();    m_deferredRepaintDelay = initialDeferredRepaintDelayDuringLoading;    m_deferredRepaintTimer.stop();    m_lastPaintTime = 0;    m_paintRestriction = PaintRestrictionNone;    m_isPainting = false;    m_isVisuallyNonEmpty = false;    m_firstVisuallyNonEmptyLayoutCallbackPending = true;}bool FrameView::isFrameView() const {     return true; }void FrameView::clearFrame(){    m_frame = 0;}void FrameView::resetScrollbars(){    // Reset the document's scrollbars back to our defaults before we yield the floor.    m_firstLayout = true;    setScrollbarsSuppressed(true);    setScrollbarModes(m_hmode, m_vmode);    setScrollbarsSuppressed(false);}void FrameView::init(){    reset();    m_margins = IntSize(-1, -1); // undefined    m_size = IntSize();    // Propagate the marginwidth/height and scrolling modes to the view.    Element* ownerElement = m_frame && m_frame->document() ? m_frame->document()->ownerElement() : 0;    if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {        HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);        if (frameElt->scrollingMode() == ScrollbarAlwaysOff)            setCanHaveScrollbars(false);        int marginWidth = frameElt->getMarginWidth();        int marginHeight = frameElt->getMarginHeight();        if (marginWidth != -1)            setMarginWidth(marginWidth);        if (marginHeight != -1)            setMarginHeight(marginHeight);    }}void FrameView::clear(){    setCanBlitOnScroll(true);        reset();    if (m_frame) {        if (RenderPart* renderer = m_frame->ownerRenderer())            renderer->viewCleared();    }    setScrollbarsSuppressed(true);}bool FrameView::didFirstLayout() const{    return !m_firstLayout;}void FrameView::initScrollbars(){    if (!m_needToInitScrollbars)        return;    m_needToInitScrollbars = false;    updateDefaultScrollbarState();}void FrameView::updateDefaultScrollbarState(){    m_hmode = horizontalScrollbarMode();    m_vmode = verticalScrollbarMode();    setScrollbarModes(m_hmode, m_vmode);}void FrameView::invalidateRect(const IntRect& rect){    if (!parent()) {        if (hostWindow())            hostWindow()->repaint(rect, true);        return;    }    if (!m_frame)        return;    RenderPart* renderer = m_frame->ownerRenderer();    if (!renderer)        return;    IntRect repaintRect = rect;    repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),                     renderer->borderTop() + renderer->paddingTop());    renderer->repaintRectangle(repaintRect);}void FrameView::setMarginWidth(int w){    // make it update the rendering area when set    m_margins.setWidth(w);}void FrameView::setMarginHeight(int h){    // make it update the rendering area when set    m_margins.setHeight(h);}void FrameView::setCanHaveScrollbars(bool canScroll){    ScrollView::setCanHaveScrollbars(canScroll);    scrollbarModes(m_hmode, m_vmode);}PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation){    // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).    Document* doc = m_frame->document();    // Try the <body> element first as a scrollbar source.    Element* body = doc->body();    if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))        return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderBox());        // If the <body> didn't have a custom style, then the root element might.    Element* docElement = doc->documentElement();    if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))        return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());            // If we have an owning iframe/frame element, then it can set the custom scrollbar also.    RenderPart* frameRenderer = m_frame->ownerRenderer();    if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))        return RenderScrollbar::createCustomScrollbar(this, orientation, frameRenderer);        // Nobody set a custom style, so we just use a native scrollbar.    return ScrollView::createScrollbar(orientation);}void FrameView::setContentsSize(const IntSize& size){    ScrollView::setContentsSize(size);    Page* page = frame() ? frame()->page() : 0;    if (!page)        return;    page->chrome()->contentsSizeChanged(frame(), size); //notify only}void FrameView::adjustViewSize(){    ASSERT(m_frame->view() == this);    RenderView* root = m_frame->contentRenderer();    if (!root)        return;    setContentsSize(IntSize(root->overflowWidth(), root->overflowHeight()));}void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode){    // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats    // overflow:hidden and overflow:scroll on <body> as applying to the document's    // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should    // use the root element.    switch (o->style()->overflowX()) {        case OHIDDEN:            hMode = ScrollbarAlwaysOff;            break;        case OSCROLL:            hMode = ScrollbarAlwaysOn;            break;        case OAUTO:            hMode = ScrollbarAuto;            break;        default:            // Don't set it at all.            ;    }         switch (o->style()->overflowY()) {        case OHIDDEN:            vMode = ScrollbarAlwaysOff;            break;        case OSCROLL:            vMode = ScrollbarAlwaysOn;            break;        case OAUTO:            vMode = ScrollbarAuto;            break;        default:            // Don't set it at all.            ;    }    m_viewportRenderer = o;}#if USE(ACCELERATED_COMPOSITING)void FrameView::updateCompositingLayers(CompositingUpdate updateType){    RenderView* view = m_frame->contentRenderer();    if (!view || !view->usesCompositing())        return;    if (updateType == ForcedCompositingUpdate)        view->compositor()->setCompositingLayersNeedUpdate();        view->compositor()->updateCompositingLayers();}void FrameView::setNeedsOneShotDrawingSynchronization(){    Page* page = frame() ? frame()->page() : 0;    if (page)        page->chrome()->client()->setNeedsOneShotDrawingSynchronization();}#endif // USE(ACCELERATED_COMPOSITING)void FrameView::didMoveOnscreen(){    RenderView* view = m_frame->contentRenderer();    if (view)        view->didMoveOnscreen();}void FrameView::willMoveOffscreen(){    RenderView* view = m_frame->contentRenderer();    if (view)        view->willMoveOffscreen();}RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const{    return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;}void FrameView::layout(bool allowSubtree){    if (m_midLayout)        return;    m_layoutTimer.stop();    m_delayedLayout = false;    // Protect the view from being deleted during layout (in recalcStyle)    RefPtr<FrameView> protector(this);    if (!m_frame) {        // FIXME: Do we need to set m_size.width here?        // FIXME: Should we set m_size.height here too?        m_size.setWidth(layoutWidth());        return;    }        // we shouldn't enter layout() while painting    ASSERT(!isPainting());    if (isPainting())        return;    if (!allowSubtree && m_layoutRoot) {        m_layoutRoot->markContainingBlocksForLayout(false);        m_layoutRoot = 0;    }    ASSERT(m_frame->view() == this);    // This early return should be removed when rdar://5598072 is resolved. In the meantime, there is a    // gigantic CrashTracer because of this issue, and the early return will hopefully cause graceful     // failure instead.      if (m_frame->view() != this)        return;    Document* document = m_frame->document();    m_layoutSchedulingEnabled = false;    if (!m_nestedLayoutCount && m_postLayoutTasksTimer.isActive()) {        // This is a new top-level layout. If there are any remaining tasks from the previous        // layout, finish them now.        m_postLayoutTasksTimer.stop();        performPostLayoutTasks();    }    // Viewport-dependent media queries may cause us to need completely different style information.

⌨️ 快捷键说明

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