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 + -
显示快捷键?