diff options
Diffstat (limited to 'Source/WebCore/page/FrameView.cpp')
-rw-r--r-- | Source/WebCore/page/FrameView.cpp | 222 |
1 files changed, 127 insertions, 95 deletions
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp index 0dc71f6..3be999c 100644 --- a/Source/WebCore/page/FrameView.cpp +++ b/Source/WebCore/page/FrameView.cpp @@ -37,6 +37,7 @@ #include "FloatRect.h" #include "FocusController.h" #include "Frame.h" +#include "FrameActionScheduler.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" #include "FrameTree.h" @@ -118,14 +119,6 @@ double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0; // The maximum number of updateWidgets iterations that should be done before returning. static const unsigned maxUpdateWidgetsIterations = 2; -struct ScheduledEvent { - WTF_MAKE_NONCOPYABLE(ScheduledEvent); WTF_MAKE_FAST_ALLOCATED; -public: - ScheduledEvent() { } - RefPtr<Event> m_event; - RefPtr<Node> m_eventTarget; -}; - FrameView::FrameView(Frame* frame) : m_frame(frame) , m_canHaveScrollbars(true) @@ -139,7 +132,7 @@ FrameView::FrameView(Frame* frame) , m_isTransparent(false) , m_baseBackgroundColor(Color::white) , m_mediaType("screen") - , m_enqueueEvents(0) + , m_actionScheduler(new FrameActionScheduler()) , m_overflowStatusDirty(true) , m_viewportRenderer(0) , m_wasScrolledByUser(false) @@ -148,6 +141,7 @@ FrameView::FrameView(Frame* frame) , m_shouldUpdateWhileOffscreen(true) , m_deferSetNeedsLayouts(0) , m_setNeedsLayoutWasDeferred(false) + , m_isRestoringFromBackForward(false) , m_scrollCorner(0) #if ENABLE(ANDROID_OVERFLOW_SCROLL) , m_hasOverflowScroll(false) @@ -167,6 +161,7 @@ PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize { RefPtr<FrameView> view = adoptRef(new FrameView(frame)); view->Widget::setFrameRect(IntRect(view->pos(), initialSize)); + view->setInitialBoundsSize(initialSize); view->show(); return view.release(); } @@ -175,8 +170,7 @@ FrameView::~FrameView() { if (m_hasPendingPostLayoutTasks) { m_postLayoutTasksTimer.stop(); - m_scheduledEvents.clear(); - m_enqueueEvents = 0; + m_actionScheduler->clear(); } if (AXObjectCache::accessibilityEnabled() && axObjectCache()) @@ -192,8 +186,7 @@ FrameView::~FrameView() setHasVerticalScrollbar(false); ASSERT(!m_scrollCorner); - ASSERT(m_scheduledEvents.isEmpty()); - ASSERT(!m_enqueueEvents); + ASSERT(m_actionScheduler->isEmpty()); if (m_frame) { ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); @@ -236,6 +229,7 @@ void FrameView::reset() m_isPainting = false; m_isVisuallyNonEmpty = false; m_firstVisuallyNonEmptyLayoutCallbackPending = true; + m_isRestoringFromBackForward = false; m_maintainScrollPositionAnchor = 0; } @@ -269,7 +263,7 @@ void FrameView::init() 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; + Element* ownerElement = m_frame ? m_frame->ownerElement() : 0; if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) { HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement); if (frameElt->scrollingMode() == ScrollbarAlwaysOff) @@ -675,10 +669,8 @@ bool FrameView::isEnclosedInCompositingLayer() const if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint()) return true; - if (Frame* parentFrame = m_frame->tree()->parent()) { - if (FrameView* parentView = parentFrame->view()) - return parentView->isEnclosedInCompositingLayer(); - } + if (FrameView* parentView = parentFrameView()) + return parentView->isEnclosedInCompositingLayer(); #endif return false; } @@ -844,7 +836,7 @@ void FrameView::layout(bool allowSubtree) } #ifdef INSTRUMENT_LAYOUT_SCHEDULING - if (m_firstLayout && !document->ownerElement()) + if (m_firstLayout && !m_frame->ownerElement()) printf("Elapsed time before first layout: %d\n", document->elapsedTime()); #endif } @@ -862,7 +854,12 @@ void FrameView::layout(bool allowSubtree) if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { if (m_firstLayout) { - setScrollbarsSuppressed(true); + if (!m_isRestoringFromBackForward) + setScrollbarsSuppressed(true); + else { + setScrollbarsSuppressed(false); + m_isRestoringFromBackForward = false; + } m_firstLayout = false; m_firstLayoutCallbackPending = true; @@ -901,7 +898,7 @@ void FrameView::layout(bool allowSubtree) RenderLayer* layer = root->enclosingLayer(); - pauseScheduledEvents(); + m_actionScheduler->pause(); bool disableLayoutState = false; if (subtree) { @@ -983,13 +980,12 @@ void FrameView::layout(bool allowSubtree) m_hasPendingPostLayoutTasks = true; m_postLayoutTasksTimer.startOneShot(0); if (needsLayout()) { - pauseScheduledEvents(); + m_actionScheduler->pause(); layout(); } } } else { - resumeScheduledEvents(); - ASSERT(m_enqueueEvents); + m_actionScheduler->resume(); } InspectorInstrumentation::didLayout(cookie); @@ -1069,10 +1065,8 @@ bool FrameView::useSlowRepaints() const if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque) return true; - if (Frame* parentFrame = m_frame->tree()->parent()) { - if (FrameView* parentView = parentFrame->view()) - return parentView->useSlowRepaints(); - } + if (FrameView* parentView = parentFrameView()) + return parentView->useSlowRepaints(); return false; } @@ -1082,10 +1076,8 @@ bool FrameView::useSlowRepaintsIfNotOverlapped() const if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque) return true; - if (Frame* parentFrame = m_frame->tree()->parent()) { - if (FrameView* parentView = parentFrame->view()) - return parentView->useSlowRepaintsIfNotOverlapped(); - } + if (FrameView* parentView = parentFrameView()) + return parentView->useSlowRepaintsIfNotOverlapped(); return false; } @@ -1134,6 +1126,7 @@ void FrameView::removeFixedObject() updateCanBlitOnScrollRecursively(); } +<<<<<<< HEAD #if PLATFORM(ANDROID) // When the screen size change, fixed positioned element should be updated. void FrameView::updatePositionedObjects() @@ -1156,6 +1149,64 @@ void FrameView::updatePositionedObjects() } } #endif +======= +int FrameView::scrollXForFixedPosition() const +{ + int visibleContentWidth = visibleContentRect().width(); + int maxX = contentsWidth() - visibleContentWidth; + + if (maxX == 0) + return 0; + + int x = scrollX(); + + if (x < 0) + x = 0; + else if (x > maxX) + x = maxX; + + if (!m_frame) + return x; + + float pageScaleFactor = m_frame->pageScaleFactor(); + + // When the page is scaled, the scaled "viewport" with respect to which fixed object are positioned + // doesn't move as fast as the content view, so that when the content is scrolled all the way to the + // end, the bottom of the scaled "viewport" touches the bottom of the real viewport. + float dragFactor = (contentsWidth() - visibleContentWidth * pageScaleFactor) / maxX; + + return x * dragFactor / pageScaleFactor; +} + +int FrameView::scrollYForFixedPosition() const +{ + int visibleContentHeight = visibleContentRect().height(); + + int maxY = contentsHeight() - visibleContentHeight; + if (maxY == 0) + return 0; + + int y = scrollY(); + + if (y < 0) + y = 0; + else if (y > maxY) + y = maxY; + + if (!m_frame) + return y; + + float pageScaleFactor = m_frame->pageScaleFactor(); + float dragFactor = (contentsHeight() - visibleContentHeight * pageScaleFactor) / maxY; + + return y * dragFactor / pageScaleFactor; +} + +IntSize FrameView::scrollOffsetForFixedPosition() const +{ + return IntSize(scrollXForFixedPosition(), scrollYForFixedPosition()); +} +>>>>>>> WebKit at r80534 IntPoint FrameView::currentMousePosition() const { @@ -1277,11 +1328,9 @@ bool FrameView::isOverlappedIncludingAncestors() const if (isOverlapped()) return true; - if (Frame* parentFrame = m_frame->tree()->parent()) { - if (FrameView* parentView = parentFrame->view()) { - if (parentView->isOverlapped()) - return true; - } + if (FrameView* parentView = parentFrameView()) { + if (parentView->isOverlapped()) + return true; } return false; @@ -1440,7 +1489,7 @@ const unsigned cRepaintRectUnionThreshold = 25; void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) { - ASSERT(!m_frame->document()->ownerElement()); + ASSERT(!m_frame->ownerElement()); double delay = adjustedDeferredRepaintDelay(); if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) { @@ -1776,11 +1825,12 @@ Color FrameView::baseBackgroundColor() const return m_baseBackgroundColor; } -void FrameView::setBaseBackgroundColor(Color bc) +void FrameView::setBaseBackgroundColor(const Color& backgroundColor) { - if (!bc.isValid()) - bc = Color::white; - m_baseBackgroundColor = bc; + if (!backgroundColor.isValid()) + m_baseBackgroundColor = Color::white; + else + m_baseBackgroundColor = backgroundColor; } void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent) @@ -1814,30 +1864,17 @@ bool FrameView::shouldUpdate(bool immediateRequested) const void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget) { - if (!m_enqueueEvents) { - ExceptionCode ec = 0; - eventTarget->dispatchEvent(event, ec); - return; - } - - ScheduledEvent* scheduledEvent = new ScheduledEvent; - scheduledEvent->m_event = event; - scheduledEvent->m_eventTarget = eventTarget; - m_scheduledEvents.append(scheduledEvent); + m_actionScheduler->scheduleEvent(event, eventTarget); } void FrameView::pauseScheduledEvents() { - ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents); - m_enqueueEvents++; + m_actionScheduler->pause(); } void FrameView::resumeScheduledEvents() { - m_enqueueEvents--; - if (!m_enqueueEvents) - dispatchScheduledEvents(); - ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents); + m_actionScheduler->resume(); } void FrameView::scrollToAnchor() @@ -1940,14 +1977,16 @@ void FrameView::performPostLayoutTasks() m_frame->selection()->setCaretRectNeedsUpdate(); m_frame->selection()->updateAppearance(); - if (m_firstLayoutCallbackPending) { - m_firstLayoutCallbackPending = false; - m_frame->loader()->didFirstLayout(); - } - - if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) { - m_firstVisuallyNonEmptyLayoutCallbackPending = false; - m_frame->loader()->didFirstVisuallyNonEmptyLayout(); + if (m_nestedLayoutCount <= 1) { + if (m_firstLayoutCallbackPending) { + m_firstLayoutCallbackPending = false; + m_frame->loader()->didFirstLayout(); + } + + if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) { + m_firstVisuallyNonEmptyLayoutCallbackPending = false; + m_frame->loader()->didFirstVisuallyNonEmptyLayout(); + } } RenderView* root = m_frame->contentRenderer(); @@ -1961,7 +2000,7 @@ void FrameView::performPostLayoutTasks() scrollToAnchor(); - resumeScheduledEvents(); + m_actionScheduler->resume(); if (!root->printing()) { IntSize currentSize = IntSize(width(), height()); @@ -1998,35 +2037,13 @@ void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverf m_horizontalOverflow = horizontalOverflow; m_verticalOverflow = verticalOverflow; - scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, + m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow), m_viewportRenderer->node()); } } -void FrameView::dispatchScheduledEvents() -{ - if (m_scheduledEvents.isEmpty()) - return; - - Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents; - m_scheduledEvents.clear(); - - Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end(); - for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) { - ScheduledEvent* scheduledEvent = *it; - - ExceptionCode ec = 0; - - // Only dispatch events to nodes that are in the document - if (scheduledEvent->m_eventTarget->inDocument()) - scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec); - - delete scheduledEvent; - } -} - IntRect FrameView::windowClipRect(bool clipToContents) const { ASSERT(m_frame->view() == this); @@ -2036,11 +2053,11 @@ IntRect FrameView::windowClipRect(bool clipToContents) const // Set our clip rect to be our contents. IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents)); - if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement()) + if (!m_frame || !m_frame->ownerElement()) return clipRect; // Take our owner element and get the clip rect from the enclosing layer. - Element* elt = m_frame->document()->ownerElement(); + Element* elt = m_frame->ownerElement(); RenderLayer* layer = elt->renderer()->enclosingLayer(); // FIXME: layer should never be null, but sometimes seems to be anyway. if (!layer) @@ -2208,6 +2225,15 @@ bool FrameView::hasCustomScrollbars() const return false; } +FrameView* FrameView::parentFrameView() const +{ + if (Widget* parentView = parent()) { + if (parentView->isFrameView()) + return static_cast<FrameView*>(parentView); + } + return 0; +} + void FrameView::updateControlTints() { // This is called when control tints are changed from aqua/graphite to clear and vice versa. @@ -2252,13 +2278,13 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect); - Document* document = frame()->document(); + Document* document = m_frame->document(); #ifndef NDEBUG bool fillWithRed; if (document->printing()) fillWithRed = false; // Printing, don't fill with red (can't remember why). - else if (document->ownerElement()) + else if (m_frame->ownerElement()) fillWithRed = false; // Subframe, don't fill with red. else if (isTransparent()) fillWithRed = false; // Transparent, don't fill with red. @@ -2293,6 +2319,12 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) #endif PaintBehavior oldPaintBehavior = m_paintBehavior; + + if (FrameView* parentView = parentFrameView()) { + if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers) + m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; + } + if (m_paintBehavior == PaintBehaviorNormal) document->markers()->invalidateRenderedRectsForMarkersInRect(rect); @@ -2300,7 +2332,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers; - bool isRootFrame = !document->ownerElement(); + bool isRootFrame = !m_frame->ownerElement(); if (flatteningPaint && isRootFrame) notifyWidgetsInAllFrames(WillPaintFlattened); |