Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: Source/core/page/scrolling/ScrollingCoordinator.cpp

Issue 17471008: Rework compositor touch hit testing (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Various fixes and test additions Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698