diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/page')
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/AbstractView.idl | 2 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/ChromeClient.h | 6 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/DOMWindow.cpp | 6 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/DOMWindow.h | 8 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/DOMWindow.idl | 2 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/EventHandler.cpp | 25 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/EventHandler.h | 4 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/FocusController.cpp | 176 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/Frame.cpp | 8 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/Frame.h | 1 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/FrameView.cpp | 58 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/FrameView.h | 15 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp | 38 | ||||
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/SpatialNavigation.h | 12 |
14 files changed, 253 insertions, 108 deletions
diff --git a/src/3rdparty/webkit/WebCore/page/AbstractView.idl b/src/3rdparty/webkit/WebCore/page/AbstractView.idl index 290bf4848a..e4ece0f575 100644 --- a/src/3rdparty/webkit/WebCore/page/AbstractView.idl +++ b/src/3rdparty/webkit/WebCore/page/AbstractView.idl @@ -32,7 +32,7 @@ module views { OmitConstructor ] AbstractView { readonly attribute Document document; - readonly attribute Media media; + readonly attribute Media styleMedia; }; } diff --git a/src/3rdparty/webkit/WebCore/page/ChromeClient.h b/src/3rdparty/webkit/WebCore/page/ChromeClient.h index 0bfdbaf78b..a01eef1cfd 100644 --- a/src/3rdparty/webkit/WebCore/page/ChromeClient.h +++ b/src/3rdparty/webkit/WebCore/page/ChromeClient.h @@ -222,7 +222,11 @@ namespace WebCore { virtual bool supportsFullscreenForNode(const Node*) { return false; } virtual void enterFullscreenForNode(Node*) { } virtual void exitFullscreenForNode(Node*) { } - + +#if ENABLE(TILED_BACKING_STORE) + virtual IntRect visibleRectForTiledBackingStore() const { return IntRect(); } +#endif + #if PLATFORM(MAC) virtual KeyboardUIMode keyboardUIMode() { return KeyboardAccessDefault; } diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp b/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp index dd902005ef..8dcff5ca4f 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp @@ -57,7 +57,7 @@ #include "InspectorController.h" #include "InspectorTimelineAgent.h" #include "Location.h" -#include "Media.h" +#include "StyleMedia.h" #include "MessageEvent.h" #include "Navigator.h" #include "NotificationCenter.h" @@ -1112,10 +1112,10 @@ Document* DOMWindow::document() const return m_frame->document(); } -PassRefPtr<Media> DOMWindow::media() const +PassRefPtr<StyleMedia> DOMWindow::styleMedia() const { if (!m_media) - m_media = Media::create(m_frame); + m_media = StyleMedia::create(m_frame); return m_media.get(); } diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.h b/src/3rdparty/webkit/WebCore/page/DOMWindow.h index a70713b201..cf9bc88d66 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.h +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.h @@ -56,7 +56,7 @@ namespace WebCore { class IndexedDatabaseRequest; class InspectorTimelineAgent; class Location; - class Media; + class StyleMedia; class Navigator; class Node; class NotificationCenter; @@ -187,7 +187,7 @@ namespace WebCore { // DOM Level 2 AbstractView Interface Document* document() const; // CSSOM View Module - PassRefPtr<Media> media() const; + PassRefPtr<StyleMedia> styleMedia() const; // DOM Level 2 Style Interface PassRefPtr<CSSStyleDeclaration> getComputedStyle(Element*, const String& pseudoElt) const; @@ -353,7 +353,7 @@ namespace WebCore { Console* optionalConsole() const { return m_console.get(); } Navigator* optionalNavigator() const { return m_navigator.get(); } Location* optionalLocation() const { return m_location.get(); } - Media* optionalMedia() const { return m_media.get(); } + StyleMedia* optionalMedia() const { return m_media.get(); } #if ENABLE(DOM_STORAGE) Storage* optionalSessionStorage() const { return m_sessionStorage.get(); } Storage* optionalLocalStorage() const { return m_localStorage.get(); } @@ -390,7 +390,7 @@ namespace WebCore { mutable RefPtr<Console> m_console; mutable RefPtr<Navigator> m_navigator; mutable RefPtr<Location> m_location; - mutable RefPtr<Media> m_media; + mutable RefPtr<StyleMedia> m_media; #if ENABLE(DOM_STORAGE) mutable RefPtr<Storage> m_sessionStorage; mutable RefPtr<Storage> m_localStorage; diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.idl b/src/3rdparty/webkit/WebCore/page/DOMWindow.idl index 31e4d4fee8..33e49e83f7 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.idl +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.idl @@ -141,7 +141,7 @@ module window { readonly attribute Document document; // CSSOM View Module - readonly attribute Media media; + readonly attribute StyleMedia styleMedia; // DOM Level 2 Style Interface CSSStyleDeclaration getComputedStyle(in Element element, diff --git a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp index 0a0e8c6458..c40299cf9a 100644 --- a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp +++ b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp @@ -230,6 +230,9 @@ void EventHandler::clear() m_capturingMouseEventsNode = 0; m_latchedWheelEventNode = 0; m_previousWheelScrolledNode = 0; +#if ENABLE(TOUCH_EVENTS) + m_originatingTouchPointTargets.clear(); +#endif } void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result) @@ -926,9 +929,13 @@ void EventHandler::setMousePressNode(PassRefPtr<Node> node) m_mousePressNode = node; } -bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity) +bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode) { - Node* node = m_frame->document()->focusedNode(); + Node* node = startingNode; + + if (!node) + node = m_frame->document()->focusedNode(); + if (!node) node = m_mousePressNode.get(); @@ -943,9 +950,9 @@ bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity g return false; } -bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity) +bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode) { - bool handled = scrollOverflow(direction, granularity); + bool handled = scrollOverflow(direction, granularity, startingNode); if (!handled) { Frame* frame = m_frame; do { @@ -2714,21 +2721,21 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap. unsigned touchPointTargetKey = point.id() + 1; - EventTarget* touchTarget = 0; + RefPtr<EventTarget> touchTarget; if (point.state() == PlatformTouchPoint::TouchPressed) { m_originatingTouchPointTargets.set(touchPointTargetKey, target); touchTarget = target; } else if (point.state() == PlatformTouchPoint::TouchReleased || point.state() == PlatformTouchPoint::TouchCancelled) { // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel // we also remove it from the map. - touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey).get(); + touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey); } else - touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey).get(); + touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey); - if (!touchTarget) + if (!touchTarget.get()) continue; - RefPtr<Touch> touch = Touch::create(doc->frame(), touchTarget, point.id(), + RefPtr<Touch> touch = Touch::create(doc->frame(), touchTarget.get(), point.id(), point.screenPos().x(), point.screenPos().y(), adjustedPageX, adjustedPageY); diff --git a/src/3rdparty/webkit/WebCore/page/EventHandler.h b/src/3rdparty/webkit/WebCore/page/EventHandler.h index 282100d75b..a94e7bf3e6 100644 --- a/src/3rdparty/webkit/WebCore/page/EventHandler.h +++ b/src/3rdparty/webkit/WebCore/page/EventHandler.h @@ -130,9 +130,9 @@ public: static Frame* subframeForTargetNode(Node*); - bool scrollOverflow(ScrollDirection, ScrollGranularity); + bool scrollOverflow(ScrollDirection, ScrollGranularity, Node* startingNode = 0); - bool scrollRecursively(ScrollDirection, ScrollGranularity); + bool scrollRecursively(ScrollDirection, ScrollGranularity, Node* startingNode = 0); #if ENABLE(DRAG_SUPPORT) bool shouldDragAutoNode(Node*, const IntPoint&) const; // -webkit-user-drag == auto diff --git a/src/3rdparty/webkit/WebCore/page/FocusController.cpp b/src/3rdparty/webkit/WebCore/page/FocusController.cpp index 6c2a956fc6..a285e52dd1 100644 --- a/src/3rdparty/webkit/WebCore/page/FocusController.cpp +++ b/src/3rdparty/webkit/WebCore/page/FocusController.cpp @@ -319,7 +319,7 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa // if |node| element is not in the viewport. if (hasOffscreenRect(node)) { Frame* frame = node->document()->view()->frame(); - scrollInDirection(frame, direction); + scrollInDirection(frame, direction, focusCandidate); return true; } @@ -341,105 +341,152 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa return true; } -// FIXME: Make this method more modular, and simpler to understand and maintain. -static void updateFocusCandidateIfCloser(Node* focusedNode, const FocusCandidate& candidate, FocusCandidate& closest) +static void updateFocusCandidateInSameContainer(const FocusCandidate& candidate, FocusCandidate& closest) { - bool sameDocument = candidate.document() == closest.document(); - if (sameDocument) { - if (closest.alignment > candidate.alignment - || (closest.parentAlignment && candidate.alignment > closest.parentAlignment)) - return; - } else if (closest.alignment > candidate.alignment - && (closest.parentAlignment && candidate.alignment > closest.parentAlignment)) + if (closest.isNull()) { + closest = candidate; return; + } - if (candidate.alignment != None - || (closest.parentAlignment >= candidate.alignment - && closest.document() == candidate.document())) { + if (candidate.alignment == closest.alignment) { + if (candidate.distance < closest.distance) + closest = candidate; + return; + } - // If we are now in an higher precedent case, lets reset the current closest's - // distance so we force it to be bigger than any result we will get from - // spatialDistance(). - if (closest.alignment < candidate.alignment - && closest.parentAlignment < candidate.alignment) - closest.distance = maxDistance(); + if (candidate.alignment > closest.alignment) + closest = candidate; +} - closest.alignment = candidate.alignment; +static void updateFocusCandidateIfCloser(Node* focusedNode, const FocusCandidate& candidate, FocusCandidate& closest) +{ + // First, check the common case: neither candidate nor closest are + // inside scrollable content, then no need to care about enclosingScrollableBox + // heuristics or parent{Distance,Alignment}, but only distance and alignment. + if (!candidate.inScrollableContainer() && !closest.inScrollableContainer()) { + updateFocusCandidateInSameContainer(candidate, closest); + return; } - // Bail out if candidate's distance is larger than that of the closest candidate. - if (candidate.distance >= closest.distance) + bool sameContainer = candidate.document() == closest.document() && candidate.enclosingScrollableBox == closest.enclosingScrollableBox; + + // Second, if candidate and closest are in the same "container" (i.e. {i}frame or any + // scrollable block element), we can handle them as common case. + if (sameContainer) { + updateFocusCandidateInSameContainer(candidate, closest); return; + } - if (closest.isNull()) { + // Last, we are considering moving to a candidate located in a different enclosing + // scrollable box than closest. + bool isInInnerDocument = !isInRootDocument(focusedNode); + + bool sameContainerAsCandidate = isInInnerDocument ? focusedNode->document() == candidate.document() : + focusedNode->isDescendantOf(candidate.enclosingScrollableBox); + + bool sameContainerAsClosest = isInInnerDocument ? focusedNode->document() == closest.document() : + focusedNode->isDescendantOf(closest.enclosingScrollableBox); + + // sameContainerAsCandidate and sameContainerAsClosest are mutually exclusive. + ASSERT(!(sameContainerAsCandidate && sameContainerAsClosest)); + + if (sameContainerAsCandidate) { closest = candidate; return; } - // If the focused node and the candadate are in the same document and current - // closest candidate is not in an {i}frame that is preferable to get focused ... - if (focusedNode->document() == candidate.document() - && candidate.distance < closest.parentDistance) - closest = candidate; - else if (focusedNode->document() != candidate.document()) { - // If the focusedNode is in an inner document and candidate is in a - // different document, we only consider to change focus if there is not - // another already good focusable candidate in the same document as focusedNode. - if (!((isInRootDocument(candidate.node) && !isInRootDocument(focusedNode)) - && focusedNode->document() == closest.document())) + if (sameContainerAsClosest) { + // Nothing to be done. + return; + } + + // NOTE: !sameContainerAsCandidate && !sameContainerAsClosest + // If distance is shorter, and we are talking about scrollable container, + // lets compare parent distance and alignment before anything. + if (candidate.distance < closest.distance) { + if (candidate.alignment >= closest.parentAlignment + || candidate.parentAlignment == closest.parentAlignment) { closest = candidate; + return; + } + + } else if (candidate.parentDistance < closest.distance) { + if (candidate.parentAlignment >= closest.alignment) { + closest = candidate; + return; + } } } void FocusController::findFocusableNodeInDirection(Node* outer, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, - FocusCandidate& closestFocusCandidate, - const FocusCandidate& candidateParent) + FocusCandidate& closest, const FocusCandidate& candidateParent) { ASSERT(outer); ASSERT(candidateParent.isNull() || candidateParent.node->hasTagName(frameTag) - || candidateParent.node->hasTagName(iframeTag)); + || candidateParent.node->hasTagName(iframeTag) + || isScrollableContainerNode(candidateParent.node)); + + // Walk all the child nodes and update closest if we find a nearer node. + Node* node = outer; + while (node) { - // Walk all the child nodes and update closestFocusCandidate if we find a nearer node. - Node* candidate = outer; - while (candidate) { // Inner documents case. + if (node->isFrameOwnerElement()) { + deepFindFocusableNodeInDirection(node, focusedNode, direction, event, closest); - if (candidate->isFrameOwnerElement()) - deepFindFocusableNodeInDirection(candidate, focusedNode, direction, event, closestFocusCandidate); - else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) { - FocusCandidate currentFocusCandidate(candidate); + // Scrollable block elements (e.g. <div>, etc) case. + } else if (isScrollableContainerNode(node)) { + deepFindFocusableNodeInDirection(node, focusedNode, direction, event, closest); + node = node->traverseNextSibling(); + continue; + + } else if (node != focusedNode && node->isKeyboardFocusable(event)) { + FocusCandidate candidate(node); + + // There are two ways to identify we are in a recursive call from deepFindFocusableNodeInDirection + // (i.e. processing an element in an iframe, frame or a scrollable block element): + + // 1) If candidateParent is not null, and it holds the distance and alignment data of the + // parent container element itself; + // 2) Parent of outer is <frame> or <iframe>; + // 3) Parent is any other scrollable block element. + if (!candidateParent.isNull()) { + candidate.parentAlignment = candidateParent.alignment; + candidate.parentDistance = candidateParent.distance; + candidate.enclosingScrollableBox = candidateParent.node; + + } else if (!isInRootDocument(outer)) { + if (Document* document = static_cast<Document*>(outer->parent())) + candidate.enclosingScrollableBox = static_cast<Node*>(document->ownerElement()); + + } else if (isScrollableContainerNode(outer->parent())) + candidate.enclosingScrollableBox = outer->parent(); // Get distance and alignment from current candidate. - distanceDataForNode(direction, focusedNode, currentFocusCandidate); + distanceDataForNode(direction, focusedNode, candidate); // Bail out if distance is maximum. - if (currentFocusCandidate.distance == maxDistance()) { - candidate = candidate->traverseNextNode(outer->parent()); + if (candidate.distance == maxDistance()) { + node = node->traverseNextNode(outer->parent()); continue; } - // If candidateParent is not null, it means that we are in a recursive call - // from deepFineFocusableNodeInDirection (i.e. processing an element in an iframe), - // and holds the distance and alignment data of the iframe element itself. - if (!candidateParent.isNull()) { - currentFocusCandidate.parentAlignment = candidateParent.alignment; - currentFocusCandidate.parentDistance = candidateParent.distance; - } - - updateFocusCandidateIfCloser(focusedNode, currentFocusCandidate, closestFocusCandidate); + updateFocusCandidateIfCloser(focusedNode, candidate, closest); } - candidate = candidate->traverseNextNode(outer->parent()); + node = node->traverseNextNode(outer->parent()); } } void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, - FocusCandidate& closestFocusCandidate) + FocusCandidate& closest) { - ASSERT(container->hasTagName(frameTag) || container->hasTagName(iframeTag)); + ASSERT(container->hasTagName(frameTag) + || container->hasTagName(iframeTag) + || isScrollableContainerNode(container)); // Track if focusedNode is a descendant of the current container node being processed. bool descendantOfContainer = false; @@ -459,10 +506,15 @@ void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* fo descendantOfContainer = innerDocument == focusedNode->document(); firstChild = innerDocument->firstChild(); + // Scrollable block elements (e.g. <div>, etc) + } else if (isScrollableContainerNode(container)) { + + firstChild = container->firstChild(); + descendantOfContainer = focusedNode->isDescendantOf(container); } if (descendantOfContainer) { - findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate); + findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest); return; } @@ -476,8 +528,8 @@ void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* fo return; // FIXME: Consider alignment? - if (candidateParent.distance < closestFocusCandidate.distance) - findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate, candidateParent); + if (candidateParent.distance < closest.distance) + findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest, candidateParent); } static bool relinquishesEditingFocus(Node *node) diff --git a/src/3rdparty/webkit/WebCore/page/Frame.cpp b/src/3rdparty/webkit/WebCore/page/Frame.cpp index 6dbca69246..379bf7d816 100644 --- a/src/3rdparty/webkit/WebCore/page/Frame.cpp +++ b/src/3rdparty/webkit/WebCore/page/Frame.cpp @@ -37,6 +37,7 @@ #include "CSSPropertyNames.h" #include "CachedCSSStyleSheet.h" #include "Chrome.h" +#include "ChromeClient.h" #include "DOMWindow.h" #include "DocLoader.h" #include "DocumentType.h" @@ -1853,6 +1854,13 @@ IntRect Frame::tiledBackingStoreContentsRect() return IntRect(); return IntRect(IntPoint(), m_view->contentsSize()); } + +IntRect Frame::tiledBackingStoreVisibleRect() +{ + if (!m_page) + return IntRect(); + return m_page->chrome()->client()->visibleRectForTiledBackingStore(); +} #endif } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Frame.h b/src/3rdparty/webkit/WebCore/page/Frame.h index 67761f9475..a654cd718f 100644 --- a/src/3rdparty/webkit/WebCore/page/Frame.h +++ b/src/3rdparty/webkit/WebCore/page/Frame.h @@ -288,6 +288,7 @@ namespace WebCore { virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&); virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea); virtual IntRect tiledBackingStoreContentsRect(); + virtual IntRect tiledBackingStoreVisibleRect(); #endif #if PLATFORM(MAC) diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.cpp b/src/3rdparty/webkit/WebCore/page/FrameView.cpp index 39c92de43f..a53db367f8 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameView.cpp +++ b/src/3rdparty/webkit/WebCore/page/FrameView.cpp @@ -80,23 +80,25 @@ using namespace HTMLNames; double FrameView::sCurrentPaintTimeStamp = 0.0; +// REPAINT_THROTTLING now chooses default values for throttling parameters. +// Should be removed when applications start using runtime configuration. #if ENABLE(REPAINT_THROTTLING) // Normal delay -static const double deferredRepaintDelay = 0.025; +double FrameView::s_deferredRepaintDelay = 0.025; // Negative value would mean that first few repaints happen without a delay -static const double initialDeferredRepaintDelayDuringLoading = 0; +double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; // The delay grows on each repaint to this maximum value -static const double maxDeferredRepaintDelayDuringLoading = 2.5; +double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5; // On each repaint the delay increses by this amount -static const double deferredRepaintDelayIncrementDuringLoading = 0.5; +double FrameView::s_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; +double FrameView::s_deferredRepaintDelay = 0; +double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; +double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0; +double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0; #endif // The maximum number of updateWidgets iterations that should be done before returning. @@ -200,7 +202,7 @@ void FrameView::reset() m_deferringRepaints = 0; m_repaintCount = 0; m_repaintRects.clear(); - m_deferredRepaintDelay = initialDeferredRepaintDelayDuringLoading; + m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading; m_deferredRepaintTimer.stop(); m_lastPaintTime = 0; m_paintBehavior = PaintBehaviorNormal; @@ -1060,7 +1062,11 @@ void FrameView::setScrollPosition(const IntPoint& scrollPoint) void FrameView::scrollPositionChanged() { frame()->eventHandler()->sendScrollEvent(); + repaintFixedElementsAfterScrolling(); +} +void FrameView::repaintFixedElementsAfterScrolling() +{ // For fixed position elements, update widget positions and compositing layers after scrolling, // but only if we're not inside of layout. // FIXME: we could skip this if we knew the page had no fixed position elements. @@ -1214,13 +1220,13 @@ void FrameView::updateDeferredRepaintDelay() { Document* document = m_frame->document(); if (!document || (!document->parsing() && !document->docLoader()->requestCount())) { - m_deferredRepaintDelay = deferredRepaintDelay; + m_deferredRepaintDelay = s_deferredRepaintDelay; return; } - if (m_deferredRepaintDelay < maxDeferredRepaintDelayDuringLoading) { - m_deferredRepaintDelay += deferredRepaintDelayIncrementDuringLoading; - if (m_deferredRepaintDelay > maxDeferredRepaintDelayDuringLoading) - m_deferredRepaintDelay = maxDeferredRepaintDelayDuringLoading; + if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) { + m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading; + if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading) + m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading; } } @@ -2139,4 +2145,28 @@ IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const return parentPoint; } +// Normal delay +void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p) +{ + s_deferredRepaintDelay = p; +} + +// Negative value would mean that first few repaints happen without a delay +void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p) +{ + s_initialDeferredRepaintDelayDuringLoading = p; +} + +// The delay grows on each repaint to this maximum value +void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p) +{ + s_maxDeferredRepaintDelayDuringLoading = p; +} + +// On each repaint the delay increases by this amount +void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p) +{ + s_deferredRepaintDelayIncrementDuringLoading = p; +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.h b/src/3rdparty/webkit/WebCore/page/FrameView.h index 7371d13643..71fa8cd9ae 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameView.h +++ b/src/3rdparty/webkit/WebCore/page/FrameView.h @@ -140,6 +140,7 @@ public: virtual void scrollRectIntoViewRecursively(const IntRect&); virtual void setScrollPosition(const IntPoint&); void scrollPositionChanged(); + virtual void repaintFixedElementsAfterScrolling(); String mediaType() const; void setMediaType(const String&); @@ -209,6 +210,15 @@ public: bool isFrameViewScrollCorner(RenderScrollbarPart* scrollCorner) const { return m_scrollCorner == scrollCorner; } void invalidateScrollCorner(); + // Normal delay + static void setRepaintThrottlingDeferredRepaintDelay(double p); + // Negative value would mean that first few repaints happen without a delay + static void setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p); + // The delay grows on each repaint to this maximum value + static void setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p); + // On each repaint the delay increses by this amount + static void setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p); + protected: virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); @@ -339,6 +349,11 @@ private: // Renderer to hold our custom scroll corner. RenderScrollbarPart* m_scrollCorner; + + static double s_deferredRepaintDelay; + static double s_initialDeferredRepaintDelayDuringLoading; + static double s_maxDeferredRepaintDelayDuringLoading; + static double s_deferredRepaintDelayIncrementDuringLoading; }; #if ENABLE(INSPECTOR) diff --git a/src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp index 890eacd803..1ce61c32bb 100644 --- a/src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp +++ b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp @@ -124,8 +124,11 @@ static IntRect renderRectRelativeToRootDocument(RenderObject* render) // Handle nested frames. for (Frame* frame = render->document()->frame(); frame; frame = frame->tree()->parent()) { - if (HTMLFrameOwnerElement* ownerElement = frame->ownerElement()) - rect.move(ownerElement->offsetLeft(), ownerElement->offsetTop()); + if (Element* element = static_cast<Element*>(frame->ownerElement())) { + do { + rect.move(element->offsetLeft(), element->offsetTop()); + } while ((element = element->offsetParent())); + } } return rect; @@ -444,7 +447,7 @@ bool hasOffscreenRect(Node* node) // In a bottom-up way, this method tries to scroll |frame| in a given direction // |direction|, going up in the frame tree hierarchy in case it does not succeed. -bool scrollInDirection(Frame* frame, FocusDirection direction) +bool scrollInDirection(Frame* frame, FocusDirection direction, const FocusCandidate& candidate) { if (!frame) return false; @@ -468,6 +471,9 @@ bool scrollInDirection(Frame* frame, FocusDirection direction) return false; } + if (!candidate.isNull() && isScrollableContainerNode(candidate.enclosingScrollableBox)) + return frame->eventHandler()->scrollRecursively(scrollDirection, ScrollByLine, candidate.enclosingScrollableBox); + return frame->eventHandler()->scrollRecursively(scrollDirection, ScrollByLine); } @@ -477,9 +483,8 @@ void scrollIntoView(Element* element) // it is preferable to inflate |element|'s bounding rect a bit before // scrolling it for accurate reason. // Element's scrollIntoView method does not provide this flexibility. - static const int fudgeFactor = 2; IntRect bounds = element->getRect(); - bounds.inflate(fudgeFactor); + bounds.inflate(fudgeFactor()); element->renderer()->enclosingLayer()->scrollRectToVisible(bounds); } @@ -497,14 +502,14 @@ static void deflateIfOverlapped(IntRect& a, IntRect& b) if (!a.intersects(b) || a.contains(b) || b.contains(a)) return; - static const int fudgeFactor = -2; + int deflateFactor = -fudgeFactor(); // Avoid negative width or height values. - if ((a.width() + 2 * fudgeFactor > 0) && (a.height() + 2 * fudgeFactor > 0)) - a.inflate(fudgeFactor); + if ((a.width() + 2 * deflateFactor > 0) && (a.height() + 2 * deflateFactor > 0)) + a.inflate(deflateFactor); - if ((b.width() + 2 * fudgeFactor > 0) && (b.height() + 2 * fudgeFactor > 0)) - b.inflate(fudgeFactor); + if ((b.width() + 2 * deflateFactor > 0) && (b.height() + 2 * deflateFactor > 0)) + b.inflate(deflateFactor); } static bool checkNegativeCoordsForNode(Node* node, const IntRect& curRect) @@ -527,4 +532,17 @@ static bool checkNegativeCoordsForNode(Node* node, const IntRect& curRect) return canBeScrolled; } +bool isScrollableContainerNode(Node* node) +{ + if (!node) + return false; + + if (RenderObject* renderer = node->renderer()) { + return (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea() + && node->hasChildNodes() && !node->isDocumentNode()); + } + + return false; +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/SpatialNavigation.h b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.h index 90ff1cf0e6..06389a3a58 100644 --- a/src/3rdparty/webkit/WebCore/page/SpatialNavigation.h +++ b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.h @@ -40,6 +40,11 @@ inline long long maxDistance() return numeric_limits<long long>::max(); } +inline unsigned int fudgeFactor() +{ + return 2; +} + // Spatially speaking, two given elements in a web page can be: // 1) Fully aligned: There is a full intersection between the rects, either // vertically or horizontally. @@ -92,6 +97,7 @@ enum RectsAlignment { struct FocusCandidate { FocusCandidate() : node(0) + , enclosingScrollableBox(0) , distance(maxDistance()) , parentDistance(maxDistance()) , alignment(None) @@ -101,6 +107,7 @@ struct FocusCandidate { FocusCandidate(Node* n) : node(n) + , enclosingScrollableBox(0) , distance(maxDistance()) , parentDistance(maxDistance()) , alignment(None) @@ -109,9 +116,11 @@ struct FocusCandidate { } bool isNull() const { return !node; } + bool inScrollableContainer() const { return node && enclosingScrollableBox; } Document* document() const { return node ? node->document() : 0; } Node* node; + Node* enclosingScrollableBox; long long distance; long long parentDistance; RectsAlignment alignment; @@ -119,10 +128,11 @@ struct FocusCandidate { }; void distanceDataForNode(FocusDirection direction, Node* start, FocusCandidate& candidate); -bool scrollInDirection(Frame*, FocusDirection); +bool scrollInDirection(Frame*, FocusDirection, const FocusCandidate& candidate = FocusCandidate()); void scrollIntoView(Element*); bool hasOffscreenRect(Node*); bool isInRootDocument(Node*); +bool isScrollableContainerNode(Node*); } // namspace WebCore |