diff options
author | fsamuel <fsamuel@chromium.org> | 2015-12-06 06:54:05 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-06 14:55:08 +0000 |
commit | a40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498 (patch) | |
tree | fca19c1e1f0b0c49f567c661ea35e7c4580f5a68 /cc/surfaces | |
parent | 79adad4e7973e44df1ee34b4952c2bfade88ee01 (diff) | |
download | chromium_src-a40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498.zip chromium_src-a40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498.tar.gz chromium_src-a40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498.tar.bz2 |
cc: Allow Surfaces clients to customize hit testing
Until we have a better hit testing data structure based on
slimming paint work, Mus needs to annotate surfaces hit
testing with additional information for shadows.
This CL provides a generic customization hook to allow a
Surfaces client to make a hit testing decision based on
factors unknown to cc.
Note that this is a short term solution until we have a
better hit testing data structure from slimming paint.
BUG=548424
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1503553002
Cr-Commit-Position: refs/heads/master@{#363371}
Diffstat (limited to 'cc/surfaces')
-rw-r--r-- | cc/surfaces/BUILD.gn | 1 | ||||
-rw-r--r-- | cc/surfaces/surface_hittest.cc | 12 | ||||
-rw-r--r-- | cc/surfaces/surface_hittest.h | 5 | ||||
-rw-r--r-- | cc/surfaces/surface_hittest_delegate.h | 24 | ||||
-rw-r--r-- | cc/surfaces/surface_hittest_unittest.cc | 143 |
5 files changed, 173 insertions, 12 deletions
diff --git a/cc/surfaces/BUILD.gn b/cc/surfaces/BUILD.gn index 6dd7240..cfb42b7 100644 --- a/cc/surfaces/BUILD.gn +++ b/cc/surfaces/BUILD.gn @@ -33,6 +33,7 @@ component("surfaces") { "surface_factory_client.h", "surface_hittest.cc", "surface_hittest.h", + "surface_hittest_delegate.h", "surface_id_allocator.cc", "surface_id_allocator.h", "surface_manager.cc", diff --git a/cc/surfaces/surface_hittest.cc b/cc/surfaces/surface_hittest.cc index b7414de..1f443d6 100644 --- a/cc/surfaces/surface_hittest.cc +++ b/cc/surfaces/surface_hittest.cc @@ -10,15 +10,16 @@ #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/surface_draw_quad.h" #include "cc/surfaces/surface.h" +#include "cc/surfaces/surface_hittest_delegate.h" #include "cc/surfaces/surface_manager.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/transform.h" namespace cc { -namespace { -} -SurfaceHittest::SurfaceHittest(SurfaceManager* manager) : manager_(manager) {} +SurfaceHittest::SurfaceHittest(SurfaceHittestDelegate* delegate, + SurfaceManager* manager) + : delegate_(delegate), manager_(manager) {} SurfaceHittest::~SurfaceHittest() {} @@ -95,6 +96,11 @@ bool SurfaceHittest::GetTargetSurfaceAtPointInternal( // Surface. const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad); + if (delegate_ && + delegate_->RejectHitTarget(surface_quad, point_in_quad_space)) { + continue; + } + gfx::Transform transform_to_child_space; if (GetTargetSurfaceAtPointInternal( surface_quad->surface_id, RenderPassId(), point_in_quad_space, diff --git a/cc/surfaces/surface_hittest.h b/cc/surfaces/surface_hittest.h index 60fa893..ce45a90 100644 --- a/cc/surfaces/surface_hittest.h +++ b/cc/surfaces/surface_hittest.h @@ -16,16 +16,18 @@ class Transform; } namespace cc { + class DrawQuad; class QuadList; class RenderPass; class RenderPassId; +class SurfaceHittestDelegate; class SurfaceManager; // Performs a hittest in surface quads. class CC_SURFACES_EXPORT SurfaceHittest { public: - explicit SurfaceHittest(SurfaceManager* manager); + SurfaceHittest(SurfaceHittestDelegate* delegate, SurfaceManager* manager); ~SurfaceHittest(); // Returns the target surface that falls underneath the provided |point|. @@ -67,6 +69,7 @@ class CC_SURFACES_EXPORT SurfaceHittest { gfx::Transform* target_to_quad_transform, gfx::Point* point_in_quad_space); + SurfaceHittestDelegate* const delegate_; SurfaceManager* const manager_; }; } // namespace cc diff --git a/cc/surfaces/surface_hittest_delegate.h b/cc/surfaces/surface_hittest_delegate.h new file mode 100644 index 0000000..1f0fbf9 --- /dev/null +++ b/cc/surfaces/surface_hittest_delegate.h @@ -0,0 +1,24 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_ +#define CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_ + +namespace cc { + +class SurfaceDrawQuad; + +// Clients of SurfaceHittest can provide a SurfaceHittestDelegate implementation +// to override the hit target based on metadata outside of the Surfaces system. +class SurfaceHittestDelegate { + public: + // Return true if this delegate rejects this |surface_quad| as a candidate hit + // target. + virtual bool RejectHitTarget(const SurfaceDrawQuad* surface_quad, + const gfx::Point& point_in_quad_space) = 0; +}; + +} // namespace cc + +#endif // CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_ diff --git a/cc/surfaces/surface_hittest_unittest.cc b/cc/surfaces/surface_hittest_unittest.cc index 2b59f0a..144d0d6 100644 --- a/cc/surfaces/surface_hittest_unittest.cc +++ b/cc/surfaces/surface_hittest_unittest.cc @@ -25,8 +25,11 @@ struct TestCase { gfx::Point expected_output_point; }; -void RunTests(SurfaceManager* manager, TestCase* tests, size_t test_count) { - SurfaceHittest hittest(manager); +void RunTests(SurfaceHittestDelegate* delegate, + SurfaceManager* manager, + TestCase* tests, + size_t test_count) { + SurfaceHittest hittest(delegate, manager); for (size_t i = 0; i < test_count; ++i) { const TestCase& test = tests[i]; gfx::Point point(test.input_point); @@ -83,7 +86,7 @@ TEST(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) { SurfaceFactory::DrawCallback()); { - SurfaceHittest hittest(&manager); + SurfaceHittest hittest(nullptr, &manager); // It is expected this test will complete without crashes. gfx::Transform transform; EXPECT_EQ(root_surface_id, @@ -120,7 +123,7 @@ TEST(SurfaceHittestTest, Hittest_SingleSurface) { }, }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); factory.Destroy(root_surface_id); } @@ -215,7 +218,7 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) { } }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); // Submit another root frame, with a slightly perturbed child Surface. root_frame = CreateCompositorFrame(root_rect, &root_pass); @@ -233,7 +236,7 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) { // Verify that point (100, 100) no longer falls on the child surface. // Verify that the transform to the child surface's space has also shifted. { - SurfaceHittest hittest(&manager); + SurfaceHittest hittest(nullptr, &manager); gfx::Point point(100, 100); gfx::Transform transform; @@ -355,7 +358,7 @@ TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) { } }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); factory.Destroy(root_surface_id); factory.Destroy(child_surface_id); @@ -459,7 +462,131 @@ TEST(SurfaceHittestTest, Hittest_RenderPassDrawQuad) { } }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); + + factory.Destroy(root_surface_id); +} + +TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) { + SurfaceManager manager; + EmptySurfaceFactoryClient client; + SurfaceFactory factory(&manager, &client); + + // Creates a root surface. + gfx::Rect root_rect(300, 300); + RenderPass* root_pass = nullptr; + scoped_ptr<CompositorFrame> root_frame = + CreateCompositorFrame(root_rect, &root_pass); + + // Add a reference to the child surface on the root surface. + SurfaceIdAllocator child_allocator(3); + SurfaceId child_surface_id = child_allocator.GenerateId(); + gfx::Rect child_rect(200, 200); + CreateSurfaceDrawQuad( + root_pass, + gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, + 0.0f, 1.0f, 0.0f, 50.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f), + root_rect, child_rect, child_surface_id); + + // Submit the root frame. + SurfaceIdAllocator root_allocator(2); + SurfaceId root_surface_id = root_allocator.GenerateId(); + factory.Create(root_surface_id); + factory.SubmitCompositorFrame(root_surface_id, std::move(root_frame), + SurfaceFactory::DrawCallback()); + + // Creates a child surface. + RenderPass* child_pass = nullptr; + scoped_ptr<CompositorFrame> child_frame = + CreateCompositorFrame(child_rect, &child_pass); + + // Add a solid quad in the child surface. + gfx::Rect child_solid_quad_rect(200, 200); + CreateSolidColorDrawQuad( + child_pass, + gfx::Transform(), + root_rect, child_solid_quad_rect); + + // Submit the frame. + factory.Create(child_surface_id); + factory.SubmitCompositorFrame(child_surface_id, std::move(child_frame), + SurfaceFactory::DrawCallback()); + + TestCase test_expectations_without_insets[] = { + { + root_surface_id, + gfx::Point(50, 50), + child_surface_id, + gfx::Point(0, 0) + }, + { + root_surface_id, + gfx::Point(60, 60), + child_surface_id, + gfx::Point(10, 10) + }, + { + root_surface_id, + gfx::Point(239, 239), + child_surface_id, + gfx::Point(189, 189) + }, + { + root_surface_id, + gfx::Point(249, 249), + child_surface_id, + gfx::Point(199, 199) + }, + }; + + TestSurfaceHittestDelegate delegate; + RunTests(&delegate, &manager, test_expectations_without_insets, + arraysize(test_expectations_without_insets)); + + // Verify that insets have NOT affected hit targeting. + EXPECT_EQ(0, delegate.target_overrides()); + + delegate.AddInsetsForSurface(child_surface_id, gfx::Insets(10, 10, 10, 10)); + + TestCase test_expectations_with_insets[] = { + // Point (50, 50) falls outside the child surface due to the insets + // introduced above. + { + root_surface_id, + gfx::Point(50, 50), + root_surface_id, + gfx::Point(50, 50) + }, + // These two points still fall within the child surface. + { + root_surface_id, + gfx::Point(60, 60), + child_surface_id, + gfx::Point(10, 10) + }, + { + root_surface_id, + gfx::Point(239, 239), + child_surface_id, + gfx::Point(189, 189) + }, + // Point (249, 249) falls outside the child surface due to the insets + // introduced above. + { + root_surface_id, + gfx::Point(249, 249), + root_surface_id, + gfx::Point(249, 249) + }, + }; + + RunTests(&delegate, &manager, test_expectations_with_insets, + arraysize(test_expectations_with_insets)); + + // Verify that insets have affected hit targeting. + EXPECT_EQ(2, delegate.target_overrides()); factory.Destroy(root_surface_id); } |