OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 10 matching lines...) Expand all Loading... |
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 | 27 |
28 #include "core/page/scrolling/ScrollingCoordinator.h" | 28 #include "core/page/scrolling/ScrollingCoordinator.h" |
29 | 29 |
30 #include "core/dom/Document.h" | 30 #include "core/dom/Document.h" |
| 31 #include "core/dom/Node.h" |
| 32 #include "core/html/HTMLElement.h" |
31 #include "core/page/Frame.h" | 33 #include "core/page/Frame.h" |
32 #include "core/page/FrameView.h" | 34 #include "core/page/FrameView.h" |
33 #include "core/page/Page.h" | 35 #include "core/page/Page.h" |
34 #include "core/platform/PlatformWheelEvent.h" | 36 #include "core/platform/PlatformWheelEvent.h" |
35 #include "core/platform/ScrollAnimator.h" | 37 #include "core/platform/ScrollAnimator.h" |
36 #include "core/platform/ScrollbarThemeComposite.h" | 38 #include "core/platform/ScrollbarThemeComposite.h" |
| 39 #include "core/platform/chromium/TraceEvent.h" |
37 #include "core/platform/chromium/support/WebScrollbarImpl.h" | 40 #include "core/platform/chromium/support/WebScrollbarImpl.h" |
38 #include "core/platform/chromium/support/WebScrollbarThemeGeometryNative.h" | 41 #include "core/platform/chromium/support/WebScrollbarThemeGeometryNative.h" |
39 #include "core/platform/graphics/GraphicsLayer.h" | 42 #include "core/platform/graphics/GraphicsLayer.h" |
40 #include "core/platform/graphics/IntRect.h" | 43 #include "core/platform/graphics/IntRect.h" |
41 #include "core/platform/graphics/Region.h" | 44 #include "core/platform/graphics/Region.h" |
42 #include "core/plugins/PluginView.h" | 45 #include "core/plugins/PluginView.h" |
43 #include "core/rendering/RenderLayerBacking.h" | 46 #include "core/rendering/RenderLayerBacking.h" |
44 #include "core/rendering/RenderLayerCompositor.h" | 47 #include "core/rendering/RenderLayerCompositor.h" |
45 #include "core/rendering/RenderView.h" | 48 #include "core/rendering/RenderView.h" |
46 #include "public/platform/Platform.h" | 49 #include "public/platform/Platform.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 WebVector<WebRect> webRects(rects.size()); | 100 WebVector<WebRect> webRects(rects.size()); |
98 for (size_t i = 0; i < rects.size(); ++i) | 101 for (size_t i = 0; i < rects.size(); ++i) |
99 webRects[i] = rects[i]; | 102 webRects[i] = rects[i]; |
100 scrollLayer->setNonFastScrollableRegion(webRects); | 103 scrollLayer->setNonFastScrollableRegion(webRects); |
101 } | 104 } |
102 } | 105 } |
103 | 106 |
104 void ScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView) | 107 void ScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView) |
105 { | 108 { |
106 ASSERT(m_page); | 109 ASSERT(m_page); |
| 110 TRACE_EVENT0("input", "ScrollingCoordinator::frameViewLayoutUpdated"); |
107 | 111 |
108 // Compute the region of the page that we can't handle scroll gestures on im
pl thread: | 112 // Compute the region of the page that we can't handle scroll gestures on im
pl thread: |
109 // This currently includes: | 113 // This currently includes: |
110 // 1. All scrollable areas, such as subframes, overflow divs and list boxes,
whose composited | 114 // 1. All scrollable areas, such as subframes, overflow divs and list boxes,
whose composited |
111 // scrolling are not enabled. We need to do this even if the frame view whos
e layout was updated | 115 // scrolling are not enabled. We need to do this even if the frame view whos
e layout was updated |
112 // is not the main frame. | 116 // is not the main frame. |
113 // 2. Resize control areas, e.g. the small rect at the right bottom of div/t
extarea/iframe when | 117 // 2. Resize control areas, e.g. the small rect at the right bottom of div/t
extarea/iframe when |
114 // CSS property "resize" is enabled. | 118 // CSS property "resize" is enabled. |
115 // 3. Plugin areas. | 119 // 3. Plugin areas. |
116 Region shouldHandleScrollGestureOnMainThreadRegion = computeShouldHandleScro
llGestureOnMainThreadRegion(m_page->mainFrame(), IntPoint()); | 120 Region shouldHandleScrollGestureOnMainThreadRegion = computeShouldHandleScro
llGestureOnMainThreadRegion(m_page->mainFrame(), IntPoint()); |
117 setShouldHandleScrollGestureOnMainThreadRegion(shouldHandleScrollGestureOnMa
inThreadRegion); | 121 setShouldHandleScrollGestureOnMainThreadRegion(shouldHandleScrollGestureOnMa
inThreadRegion); |
118 Vector<IntRect> touchEventTargetRects; | 122 LayerHitTestRects touchEventTargetRects; |
119 computeAbsoluteTouchEventTargetRects(m_page->mainFrame()->document(), touchE
ventTargetRects); | 123 computeTouchEventTargetRects(touchEventTargetRects); |
120 setTouchEventTargetRects(touchEventTargetRects); | 124 setTouchEventTargetRects(touchEventTargetRects); |
121 if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(frameView)) | 125 if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(frameView)) |
122 scrollLayer->setBounds(frameView->contentsSize()); | 126 scrollLayer->setBounds(frameView->contentsSize()); |
123 } | 127 } |
124 | 128 |
125 void ScrollingCoordinator::setLayerIsContainerForFixedPositionLayers(GraphicsLay
er* layer, bool enable) | 129 void ScrollingCoordinator::setLayerIsContainerForFixedPositionLayers(GraphicsLay
er* layer, bool enable) |
126 { | 130 { |
127 if (WebLayer* scrollableLayer = scrollingWebLayerForGraphicsLayer(layer)) | 131 if (WebLayer* scrollableLayer = scrollingWebLayerForGraphicsLayer(layer)) |
128 scrollableLayer->setIsContainerForFixedPositionLayers(enable); | 132 scrollableLayer->setIsContainerForFixedPositionLayers(enable); |
129 } | 133 } |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 webLayer->setScrollable(true); | 283 webLayer->setScrollable(true); |
280 webLayer->setScrollPosition(IntPoint(scrollableArea->scrollPosition() -
scrollableArea->minimumScrollPosition())); | 284 webLayer->setScrollPosition(IntPoint(scrollableArea->scrollPosition() -
scrollableArea->minimumScrollPosition())); |
281 webLayer->setMaxScrollPosition(IntSize(scrollableArea->scrollSize(Horizo
ntalScrollbar), scrollableArea->scrollSize(VerticalScrollbar))); | 285 webLayer->setMaxScrollPosition(IntSize(scrollableArea->scrollSize(Horizo
ntalScrollbar), scrollableArea->scrollSize(VerticalScrollbar))); |
282 } | 286 } |
283 if (WebScrollbarLayer* scrollbarLayer = getWebScrollbarLayer(scrollableArea,
HorizontalScrollbar)) | 287 if (WebScrollbarLayer* scrollbarLayer = getWebScrollbarLayer(scrollableArea,
HorizontalScrollbar)) |
284 setupScrollbarLayer(horizontalScrollbarLayerForScrollableArea(scrollable
Area), scrollbarLayer, webLayer); | 288 setupScrollbarLayer(horizontalScrollbarLayerForScrollableArea(scrollable
Area), scrollbarLayer, webLayer); |
285 if (WebScrollbarLayer* scrollbarLayer = getWebScrollbarLayer(scrollableArea,
VerticalScrollbar)) | 289 if (WebScrollbarLayer* scrollbarLayer = getWebScrollbarLayer(scrollableArea,
VerticalScrollbar)) |
286 setupScrollbarLayer(verticalScrollbarLayerForScrollableArea(scrollableAr
ea), scrollbarLayer, webLayer); | 290 setupScrollbarLayer(verticalScrollbarLayerForScrollableArea(scrollableAr
ea), scrollbarLayer, webLayer); |
287 } | 291 } |
288 | 292 |
289 void ScrollingCoordinator::setTouchEventTargetRects(const Vector<IntRect>& absol
uteHitTestRects) | 293 void ScrollingCoordinator::setTouchEventTargetRects(const LayerHitTestRects& lay
erRects) |
290 { | 294 { |
291 if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(m_page->mainF
rame()->view())) { | 295 // Note that ideally we'd clear the touch event handler region on all layers
first, |
292 WebVector<WebRect> webRects(absoluteHitTestRects.size()); | 296 // in case there are others that no longer have any handlers. But it's unlik
ely to |
293 for (size_t i = 0; i < absoluteHitTestRects.size(); ++i) | 297 // matter much in practice (just makes us more conservative). |
294 webRects[i] = absoluteHitTestRects[i]; | 298 for (LayerHitTestRects::const_iterator iter = layerRects.begin(); iter != la
yerRects.end(); ++iter) { |
295 scrollLayer->setTouchEventHandlerRegion(webRects); | 299 WebVector<WebRect> webRects(iter->value.size()); |
| 300 for (size_t i = 0; i < iter->value.size(); ++i) |
| 301 webRects[i] = iter->value[i]; |
| 302 RenderLayerBacking* backing = iter->key->backing(); |
| 303 // If the layer is using composited scrolling, then it's the contents th
at these |
| 304 // rects apply to. |
| 305 GraphicsLayer* graphicsLayer = backing->scrollingContentsLayer(); |
| 306 if (!graphicsLayer) |
| 307 graphicsLayer = backing->graphicsLayer(); |
| 308 graphicsLayer->platformLayer()->setTouchEventHandlerRegion(webRects); |
296 } | 309 } |
297 } | 310 } |
298 | 311 |
299 void ScrollingCoordinator::touchEventTargetRectsDidChange(const Document*) | 312 void ScrollingCoordinator::touchEventTargetRectsDidChange(const Document*) |
300 { | 313 { |
301 // The rects are always evaluated and used in the main frame coordinates. | |
302 FrameView* frameView = m_page->mainFrame()->view(); | |
303 Document* document = m_page->mainFrame()->document(); | |
304 | |
305 // Wait until after layout to update. | 314 // Wait until after layout to update. |
306 if (frameView->needsLayout() || !document) | 315 if (m_page->mainFrame()->view()->needsLayout()) |
307 return; | 316 return; |
308 | 317 |
309 Vector<IntRect> touchEventTargetRects; | 318 LayerHitTestRects touchEventTargetRects; |
310 computeAbsoluteTouchEventTargetRects(document, touchEventTargetRects); | 319 computeTouchEventTargetRects(touchEventTargetRects); |
311 setTouchEventTargetRects(touchEventTargetRects); | 320 setTouchEventTargetRects(touchEventTargetRects); |
312 } | 321 } |
313 | 322 |
314 void ScrollingCoordinator::setWheelEventHandlerCount(unsigned count) | 323 void ScrollingCoordinator::setWheelEventHandlerCount(unsigned count) |
315 { | 324 { |
316 if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(m_page->mainF
rame()->view())) | 325 if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(m_page->mainF
rame()->view())) |
317 scrollLayer->setHaveWheelEventHandlers(count > 0); | 326 scrollLayer->setHaveWheelEventHandlers(count > 0); |
318 } | 327 } |
319 | 328 |
320 void ScrollingCoordinator::recomputeWheelEventHandlerCountForFrameView(FrameView
* frameView) | 329 void ScrollingCoordinator::recomputeWheelEventHandlerCountForFrameView(FrameView
* frameView) |
(...skipping 25 matching lines...) Expand all Loading... |
346 | 355 |
347 // We currently only support composited mode. | 356 // We currently only support composited mode. |
348 RenderView* renderView = m_page->mainFrame()->contentRenderer(); | 357 RenderView* renderView = m_page->mainFrame()->contentRenderer(); |
349 if (!renderView) | 358 if (!renderView) |
350 return false; | 359 return false; |
351 return renderView->usesCompositing(); | 360 return renderView->usesCompositing(); |
352 } | 361 } |
353 | 362 |
354 Region ScrollingCoordinator::computeShouldHandleScrollGestureOnMainThreadRegion(
const Frame* frame, const IntPoint& frameLocation) const | 363 Region ScrollingCoordinator::computeShouldHandleScrollGestureOnMainThreadRegion(
const Frame* frame, const IntPoint& frameLocation) const |
355 { | 364 { |
| 365 TRACE_EVENT0("input", "ScrollingCoordinator::computeShouldHandleScrollGestur
eOnMainThreadRegion"); |
356 Region shouldHandleScrollGestureOnMainThreadRegion; | 366 Region shouldHandleScrollGestureOnMainThreadRegion; |
357 FrameView* frameView = frame->view(); | 367 FrameView* frameView = frame->view(); |
358 if (!frameView) | 368 if (!frameView) |
359 return shouldHandleScrollGestureOnMainThreadRegion; | 369 return shouldHandleScrollGestureOnMainThreadRegion; |
360 | 370 |
361 IntPoint offset = frameLocation; | 371 IntPoint offset = frameLocation; |
362 offset.moveBy(frameView->frameRect().location()); | 372 offset.moveBy(frameView->frameRect().location()); |
363 | 373 |
364 if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrolla
bleAreas()) { | 374 if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrolla
bleAreas()) { |
365 for (FrameView::ScrollableAreaSet::const_iterator it = scrollableAreas->
begin(), end = scrollableAreas->end(); it != end; ++it) { | 375 for (FrameView::ScrollableAreaSet::const_iterator it = scrollableAreas->
begin(), end = scrollableAreas->end(); it != end; ++it) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 } | 408 } |
399 } | 409 } |
400 | 410 |
401 FrameTree* tree = frame->tree(); | 411 FrameTree* tree = frame->tree(); |
402 for (Frame* subFrame = tree->firstChild(); subFrame; subFrame = subFrame->tr
ee()->nextSibling()) | 412 for (Frame* subFrame = tree->firstChild(); subFrame; subFrame = subFrame->tr
ee()->nextSibling()) |
403 shouldHandleScrollGestureOnMainThreadRegion.unite(computeShouldHandleScr
ollGestureOnMainThreadRegion(subFrame, offset)); | 413 shouldHandleScrollGestureOnMainThreadRegion.unite(computeShouldHandleScr
ollGestureOnMainThreadRegion(subFrame, offset)); |
404 | 414 |
405 return shouldHandleScrollGestureOnMainThreadRegion; | 415 return shouldHandleScrollGestureOnMainThreadRegion; |
406 } | 416 } |
407 | 417 |
408 static void accumulateRendererTouchEventTargetRects(Vector<IntRect>& rects, cons
t RenderObject* renderer, const IntRect& parentRect = IntRect()) | 418 void ScrollingCoordinator::addTouchEventTargetRectsObserver(TouchEventTargetRect
sObserver* observer) |
409 { | 419 { |
410 IntRect adjustedParentRect = parentRect; | 420 m_touchEventTargetRectsObservers.add(observer); |
411 if (parentRect.isEmpty() || renderer->isFloating() || renderer->isPositioned
() || renderer->hasTransform()) { | |
412 // FIXME: This method is O(N^2) as it walks the tree to the root for eve
ry renderer. RenderGeometryMap would fix this. | |
413 IntRect r = enclosingIntRect(renderer->clippedOverflowRectForRepaint(0))
; | |
414 if (!r.isEmpty()) { | |
415 // Convert to the top-level view's coordinates. | |
416 ASSERT(renderer->document()->view()); | |
417 r = renderer->document()->view()->convertToRootView(r); | |
418 | |
419 if (!parentRect.contains(r)) { | |
420 rects.append(r); | |
421 adjustedParentRect = r; | |
422 } | |
423 } | |
424 } | |
425 | |
426 for (RenderObject* child = renderer->firstChild(); child; child = child->nex
tSibling()) | |
427 accumulateRendererTouchEventTargetRects(rects, child, adjustedParentRect
); | |
428 } | 421 } |
429 | 422 |
430 static void accumulateDocumentEventTargetRects(Vector<IntRect>& rects, const Doc
ument* document) | 423 void ScrollingCoordinator::removeTouchEventTargetRectsObserver(TouchEventTargetR
ectsObserver* observer) |
| 424 { |
| 425 m_touchEventTargetRectsObservers.remove(observer); |
| 426 } |
| 427 |
| 428 static void accumulateDocumentTouchEventTargetRects(LayerHitTestRects& rects, co
nst Document* document) |
431 { | 429 { |
432 ASSERT(document); | 430 ASSERT(document); |
433 if (!document->touchEventTargets()) | 431 if (!document->touchEventTargets()) |
434 return; | 432 return; |
435 | 433 |
436 const TouchEventTargetSet* targets = document->touchEventTargets(); | 434 const TouchEventTargetSet* targets = document->touchEventTargets(); |
| 435 |
| 436 // If there's a handler on the document, html or body element (fairly common
in practice), |
| 437 // then we can quickly mark the entire document and skip looking at any othe
r handlers. |
| 438 // Note that technically a handler on the body doesn't cover the whole docum
ent, but it's |
| 439 // reasonable to be conservative and report the whole document anyway. |
437 for (TouchEventTargetSet::const_iterator iter = targets->begin(); iter != ta
rgets->end(); ++iter) { | 440 for (TouchEventTargetSet::const_iterator iter = targets->begin(); iter != ta
rgets->end(); ++iter) { |
438 const Node* touchTarget = iter->key; | 441 Node* target = iter->key; |
439 if (!touchTarget->inDocument()) | 442 if (target == document || target == document->documentElement() || targe
t == document->body()) { |
440 continue; | 443 if (RenderObject* renderer = document->renderer()) { |
441 | 444 renderer->computeLayerHitTestRects(rects); |
442 if (touchTarget == document) { | |
443 if (RenderView* view = document->renderView()) { | |
444 IntRect r; | |
445 if (touchTarget == document->topDocument()) | |
446 r = view->documentRect(); | |
447 else | |
448 r = enclosingIntRect(view->clippedOverflowRectForRepaint(0))
; | |
449 | |
450 if (!r.isEmpty()) { | |
451 ASSERT(view->document()->view()); | |
452 r = view->document()->view()->convertToRootView(r); | |
453 rects.append(r); | |
454 } | |
455 } | 445 } |
456 return; | 446 return; |
457 } | 447 } |
| 448 } |
458 | 449 |
459 if (touchTarget->isDocumentNode() && touchTarget != document) { | 450 // Examine every target in detail. |
460 accumulateDocumentEventTargetRects(rects, toDocument(touchTarget)); | 451 for (TouchEventTargetSet::const_iterator iter = targets->begin(); iter != ta
rgets->end(); ++iter) { |
| 452 const Node* target = iter->key; |
| 453 if (!target->inDocument()) |
461 continue; | 454 continue; |
| 455 |
| 456 if (target->isDocumentNode()) { |
| 457 ASSERT(target != document); |
| 458 accumulateDocumentTouchEventTargetRects(rects, toDocument(target)); |
| 459 } else if (RenderObject* renderer = target->renderer()) { |
| 460 renderer->computeLayerHitTestRects(rects); |
462 } | 461 } |
| 462 } |
463 | 463 |
464 if (RenderObject* renderer = touchTarget->renderer()) | |
465 accumulateRendererTouchEventTargetRects(rects, renderer); | |
466 } | |
467 } | 464 } |
468 | 465 |
469 void ScrollingCoordinator::computeAbsoluteTouchEventTargetRects(const Document*
document, Vector<IntRect>& rects) | 466 void ScrollingCoordinator::computeTouchEventTargetRects(LayerHitTestRects& rects
) |
470 { | 467 { |
471 ASSERT(document); | 468 TRACE_EVENT0("input", "ScrollingCoordinator::computeTouchEventTargetRects"); |
472 if (!document->view()) | 469 |
| 470 Document* document = m_page->mainFrame()->document(); |
| 471 if (!document || !document->view()) |
473 return; | 472 return; |
474 | 473 |
475 // FIXME: These rects won't be properly updated if the renderers are in a su
b-tree that scrolls. | 474 accumulateDocumentTouchEventTargetRects(rects, document); |
476 accumulateDocumentEventTargetRects(rects, document); | 475 |
| 476 HashSet<TouchEventTargetRectsObserver*>::iterator stop = m_touchEventTargetR
ectsObservers.end(); |
| 477 for (HashSet<TouchEventTargetRectsObserver*>::iterator it = m_touchEventTarg
etRectsObservers.begin(); it != stop; ++it) |
| 478 (*it)->touchEventTargetRectsChanged(rects); |
477 } | 479 } |
478 | 480 |
479 unsigned ScrollingCoordinator::computeCurrentWheelEventHandlerCount() | 481 unsigned ScrollingCoordinator::computeCurrentWheelEventHandlerCount() |
480 { | 482 { |
481 unsigned wheelEventHandlerCount = 0; | 483 unsigned wheelEventHandlerCount = 0; |
482 | 484 |
483 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->trave
rseNext()) { | 485 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->trave
rseNext()) { |
484 if (frame->document()) | 486 if (frame->document()) |
485 wheelEventHandlerCount += frame->document()->wheelEventHandlerCount(
); | 487 wheelEventHandlerCount += frame->document()->wheelEventHandlerCount(
); |
486 } | 488 } |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 stringBuilder.resize(stringBuilder.length() - 2); | 635 stringBuilder.resize(stringBuilder.length() - 2); |
634 return stringBuilder.toString(); | 636 return stringBuilder.toString(); |
635 } | 637 } |
636 | 638 |
637 String ScrollingCoordinator::mainThreadScrollingReasonsAsText() const | 639 String ScrollingCoordinator::mainThreadScrollingReasonsAsText() const |
638 { | 640 { |
639 return mainThreadScrollingReasonsAsText(mainThreadScrollingReasons()); | 641 return mainThreadScrollingReasonsAsText(mainThreadScrollingReasons()); |
640 } | 642 } |
641 | 643 |
642 } // namespace WebCore | 644 } // namespace WebCore |
OLD | NEW |