| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/trees/layer_tree_host_common.h" | 5 #include "cc/trees/layer_tree_host_common.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "cc/base/math_util.h" | 10 #include "cc/base/math_util.h" |
| 11 #include "cc/layers/heads_up_display_layer_impl.h" | 11 #include "cc/layers/heads_up_display_layer_impl.h" |
| 12 #include "cc/layers/layer.h" | 12 #include "cc/layers/layer.h" |
| 13 #include "cc/layers/layer_impl.h" | 13 #include "cc/layers/layer_impl.h" |
| 14 #include "cc/layers/layer_iterator.h" | 14 #include "cc/layers/layer_iterator.h" |
| 15 #include "cc/layers/render_surface.h" | 15 #include "cc/layers/render_surface.h" |
| 16 #include "cc/layers/render_surface_impl.h" | 16 #include "cc/layers/render_surface_impl.h" |
| 17 #include "cc/trees/layer_sorter.h" | 17 #include "cc/trees/layer_sorter.h" |
| 18 #include "cc/trees/layer_tree_impl.h" | 18 #include "cc/trees/layer_tree_impl.h" |
| 19 #include "ui/gfx/point_conversions.h" | |
| 20 #include "ui/gfx/rect_conversions.h" | 19 #include "ui/gfx/rect_conversions.h" |
| 21 #include "ui/gfx/transform.h" | 20 #include "ui/gfx/transform.h" |
| 22 | 21 |
| 23 namespace cc { | 22 namespace cc { |
| 24 | 23 |
| 25 ScrollAndScaleSet::ScrollAndScaleSet() {} | 24 ScrollAndScaleSet::ScrollAndScaleSet() {} |
| 26 | 25 |
| 27 ScrollAndScaleSet::~ScrollAndScaleSet() {} | 26 ScrollAndScaleSet::~ScrollAndScaleSet() {} |
| 28 | 27 |
| 29 static void SortLayers(LayerList::iterator forst, | 28 static void SortLayers(LayerList::iterator forst, |
| (...skipping 2390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2420 &accumulated_surface_state, | 2419 &accumulated_surface_state, |
| 2421 inputs->current_render_surface_layer_list_id); | 2420 inputs->current_render_surface_layer_list_id); |
| 2422 | 2421 |
| 2423 // The dummy layer list should not have been used. | 2422 // The dummy layer list should not have been used. |
| 2424 DCHECK_EQ(0u, dummy_layer_list.size()); | 2423 DCHECK_EQ(0u, dummy_layer_list.size()); |
| 2425 // A root layer render_surface should always exist after | 2424 // A root layer render_surface should always exist after |
| 2426 // CalculateDrawProperties. | 2425 // CalculateDrawProperties. |
| 2427 DCHECK(inputs->root_layer->render_surface()); | 2426 DCHECK(inputs->root_layer->render_surface()); |
| 2428 } | 2427 } |
| 2429 | 2428 |
| 2430 static bool PointHitsRect( | |
| 2431 const gfx::PointF& screen_space_point, | |
| 2432 const gfx::Transform& local_space_to_screen_space_transform, | |
| 2433 const gfx::RectF& local_space_rect) { | |
| 2434 // If the transform is not invertible, then assume that this point doesn't hit | |
| 2435 // this rect. | |
| 2436 gfx::Transform inverse_local_space_to_screen_space( | |
| 2437 gfx::Transform::kSkipInitialization); | |
| 2438 if (!local_space_to_screen_space_transform.GetInverse( | |
| 2439 &inverse_local_space_to_screen_space)) | |
| 2440 return false; | |
| 2441 | |
| 2442 // Transform the hit test point from screen space to the local space of the | |
| 2443 // given rect. | |
| 2444 bool clipped = false; | |
| 2445 gfx::PointF hit_test_point_in_local_space = MathUtil::ProjectPoint( | |
| 2446 inverse_local_space_to_screen_space, screen_space_point, &clipped); | |
| 2447 | |
| 2448 // If ProjectPoint could not project to a valid value, then we assume that | |
| 2449 // this point doesn't hit this rect. | |
| 2450 if (clipped) | |
| 2451 return false; | |
| 2452 | |
| 2453 return local_space_rect.Contains(hit_test_point_in_local_space); | |
| 2454 } | |
| 2455 | |
| 2456 static bool PointHitsRegion(const gfx::PointF& screen_space_point, | |
| 2457 const gfx::Transform& screen_space_transform, | |
| 2458 const Region& layer_space_region, | |
| 2459 float layer_content_scale_x, | |
| 2460 float layer_content_scale_y) { | |
| 2461 // If the transform is not invertible, then assume that this point doesn't hit | |
| 2462 // this region. | |
| 2463 gfx::Transform inverse_screen_space_transform( | |
| 2464 gfx::Transform::kSkipInitialization); | |
| 2465 if (!screen_space_transform.GetInverse(&inverse_screen_space_transform)) | |
| 2466 return false; | |
| 2467 | |
| 2468 // Transform the hit test point from screen space to the local space of the | |
| 2469 // given region. | |
| 2470 bool clipped = false; | |
| 2471 gfx::PointF hit_test_point_in_content_space = MathUtil::ProjectPoint( | |
| 2472 inverse_screen_space_transform, screen_space_point, &clipped); | |
| 2473 gfx::PointF hit_test_point_in_layer_space = | |
| 2474 gfx::ScalePoint(hit_test_point_in_content_space, | |
| 2475 1.f / layer_content_scale_x, | |
| 2476 1.f / layer_content_scale_y); | |
| 2477 | |
| 2478 // If ProjectPoint could not project to a valid value, then we assume that | |
| 2479 // this point doesn't hit this region. | |
| 2480 if (clipped) | |
| 2481 return false; | |
| 2482 | |
| 2483 return layer_space_region.Contains( | |
| 2484 gfx::ToRoundedPoint(hit_test_point_in_layer_space)); | |
| 2485 } | |
| 2486 | |
| 2487 static bool PointIsClippedBySurfaceOrClipRect( | |
| 2488 const gfx::PointF& screen_space_point, | |
| 2489 LayerImpl* layer) { | |
| 2490 LayerImpl* current_layer = layer; | |
| 2491 | |
| 2492 // Walk up the layer tree and hit-test any render_surfaces and any layer | |
| 2493 // clip rects that are active. | |
| 2494 while (current_layer) { | |
| 2495 if (current_layer->render_surface() && | |
| 2496 !PointHitsRect( | |
| 2497 screen_space_point, | |
| 2498 current_layer->render_surface()->screen_space_transform(), | |
| 2499 current_layer->render_surface()->content_rect())) | |
| 2500 return true; | |
| 2501 | |
| 2502 // Note that drawable content rects are actually in target surface space, so | |
| 2503 // the transform we have to provide is the target surface's | |
| 2504 // screen_space_transform. | |
| 2505 LayerImpl* render_target = current_layer->render_target(); | |
| 2506 if (LayerClipsSubtree(current_layer) && | |
| 2507 !PointHitsRect( | |
| 2508 screen_space_point, | |
| 2509 render_target->render_surface()->screen_space_transform(), | |
| 2510 current_layer->drawable_content_rect())) | |
| 2511 return true; | |
| 2512 | |
| 2513 current_layer = current_layer->parent(); | |
| 2514 } | |
| 2515 | |
| 2516 // If we have finished walking all ancestors without having already exited, | |
| 2517 // then the point is not clipped by any ancestors. | |
| 2518 return false; | |
| 2519 } | |
| 2520 | |
| 2521 static bool PointHitsLayer(LayerImpl* layer, | |
| 2522 const gfx::PointF& screen_space_point) { | |
| 2523 gfx::RectF content_rect(layer->content_bounds()); | |
| 2524 if (!PointHitsRect( | |
| 2525 screen_space_point, layer->screen_space_transform(), content_rect)) | |
| 2526 return false; | |
| 2527 | |
| 2528 // At this point, we think the point does hit the layer, but we need to walk | |
| 2529 // up the parents to ensure that the layer was not clipped in such a way | |
| 2530 // that the hit point actually should not hit the layer. | |
| 2531 if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer)) | |
| 2532 return false; | |
| 2533 | |
| 2534 // Skip the HUD layer. | |
| 2535 if (layer == layer->layer_tree_impl()->hud_layer()) | |
| 2536 return false; | |
| 2537 | |
| 2538 return true; | |
| 2539 } | |
| 2540 | |
| 2541 LayerImpl* LayerTreeHostCommon::FindFirstScrollingLayerThatIsHitByPoint( | |
| 2542 const gfx::PointF& screen_space_point, | |
| 2543 const LayerImplList& render_surface_layer_list) { | |
| 2544 typedef LayerIterator<LayerImpl> LayerIteratorType; | |
| 2545 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list); | |
| 2546 for (LayerIteratorType it = | |
| 2547 LayerIteratorType::Begin(&render_surface_layer_list); | |
| 2548 it != end; | |
| 2549 ++it) { | |
| 2550 // We don't want to consider render_surfaces for hit testing. | |
| 2551 if (!it.represents_itself()) | |
| 2552 continue; | |
| 2553 | |
| 2554 LayerImpl* current_layer = (*it); | |
| 2555 if (!PointHitsLayer(current_layer, screen_space_point)) | |
| 2556 continue; | |
| 2557 | |
| 2558 if (current_layer->scrollable()) | |
| 2559 return current_layer; | |
| 2560 } | |
| 2561 | |
| 2562 return NULL; | |
| 2563 } | |
| 2564 | |
| 2565 LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPoint( | |
| 2566 const gfx::PointF& screen_space_point, | |
| 2567 const LayerImplList& render_surface_layer_list) { | |
| 2568 LayerImpl* found_layer = NULL; | |
| 2569 | |
| 2570 typedef LayerIterator<LayerImpl> LayerIteratorType; | |
| 2571 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list); | |
| 2572 for (LayerIteratorType | |
| 2573 it = LayerIteratorType::Begin(&render_surface_layer_list); | |
| 2574 it != end; | |
| 2575 ++it) { | |
| 2576 // We don't want to consider render_surfaces for hit testing. | |
| 2577 if (!it.represents_itself()) | |
| 2578 continue; | |
| 2579 | |
| 2580 LayerImpl* current_layer = (*it); | |
| 2581 if (!PointHitsLayer(current_layer, screen_space_point)) | |
| 2582 continue; | |
| 2583 | |
| 2584 found_layer = current_layer; | |
| 2585 break; | |
| 2586 } | |
| 2587 | |
| 2588 // This can potentially return NULL, which means the screen_space_point did | |
| 2589 // not successfully hit test any layers, not even the root layer. | |
| 2590 return found_layer; | |
| 2591 } | |
| 2592 | |
| 2593 LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion( | |
| 2594 const gfx::PointF& screen_space_point, | |
| 2595 const LayerImplList& render_surface_layer_list) { | |
| 2596 typedef LayerIterator<LayerImpl> LayerIteratorType; | |
| 2597 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list); | |
| 2598 for (LayerIteratorType it = | |
| 2599 LayerIteratorType::Begin(&render_surface_layer_list); | |
| 2600 it != end; | |
| 2601 ++it) { | |
| 2602 // We don't want to consider render_surfaces for hit testing. | |
| 2603 if (!it.represents_itself()) | |
| 2604 continue; | |
| 2605 | |
| 2606 LayerImpl* current_layer = (*it); | |
| 2607 if (!PointHitsLayer(current_layer, screen_space_point)) | |
| 2608 continue; | |
| 2609 | |
| 2610 if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(screen_space_point, | |
| 2611 current_layer)) | |
| 2612 return current_layer; | |
| 2613 | |
| 2614 // Note that we could stop searching if we hit a layer we know to be | |
| 2615 // opaque to hit-testing, but knowing that reliably is tricky (eg. due to | |
| 2616 // CSS pointer-events: none). Also blink has an optimization for the | |
| 2617 // common case of an entire document having handlers where it doesn't | |
| 2618 // report any rects for child layers (since it knows they can't exceed | |
| 2619 // the document bounds). | |
| 2620 } | |
| 2621 return NULL; | |
| 2622 } | |
| 2623 | |
| 2624 bool LayerTreeHostCommon::LayerHasTouchEventHandlersAt( | |
| 2625 const gfx::PointF& screen_space_point, | |
| 2626 LayerImpl* layer_impl) { | |
| 2627 if (layer_impl->touch_event_handler_region().IsEmpty()) | |
| 2628 return false; | |
| 2629 | |
| 2630 if (!PointHitsRegion(screen_space_point, | |
| 2631 layer_impl->screen_space_transform(), | |
| 2632 layer_impl->touch_event_handler_region(), | |
| 2633 layer_impl->contents_scale_x(), | |
| 2634 layer_impl->contents_scale_y())) | |
| 2635 return false; | |
| 2636 | |
| 2637 // At this point, we think the point does hit the touch event handler region | |
| 2638 // on the layer, but we need to walk up the parents to ensure that the layer | |
| 2639 // was not clipped in such a way that the hit point actually should not hit | |
| 2640 // the layer. | |
| 2641 if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer_impl)) | |
| 2642 return false; | |
| 2643 | |
| 2644 return true; | |
| 2645 } | |
| 2646 } // namespace cc | 2429 } // namespace cc |
| OLD | NEW |