1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_COMMON_HIT_TEST_HIT_TEST_QUERY_H_
#define COMPONENTS_VIZ_COMMON_HIT_TEST_HIT_TEST_QUERY_H_
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/safe_ref.h"
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/common/viz_common_export.h"
#include "ui/gfx/geometry/point_f.h"
namespace viz {
struct Target {
FrameSinkId frame_sink_id;
// Coordinates in the coordinate system of the target FrameSinkId.
gfx::PointF location_in_target;
// Different flags are defined in services/viz/public/mojom/hit_test/
// hit_test_region_list.mojom.
uint32_t flags = 0;
};
enum class EventSource {
MOUSE,
TOUCH,
ANY,
};
// Finds the target for a given location based on the AggregatedHitTestRegion
// list aggregated by HitTestAggregator.
// TODO(crbug.com/41460939): Handle 3d space cases correctly.
class VIZ_COMMON_EXPORT HitTestQuery {
public:
class DataProvider {
public:
virtual ~DataProvider() = default;
// Gets HitTestData from `HitTestAggregator` on VizCompositor thread.
virtual const std::vector<AggregatedHitTestRegion>& GetHitTestData()
const = 0;
};
explicit HitTestQuery(std::optional<base::SafeRef<DataProvider>> provider);
HitTestQuery(const HitTestQuery&) = delete;
HitTestQuery& operator=(const HitTestQuery&) = delete;
virtual ~HitTestQuery();
// HitTestAggregator has sent the most recent |hit_test_data| for targeting/
// transforming requests.
void OnAggregatedHitTestRegionListUpdated(
const std::vector<AggregatedHitTestRegion>& hit_test_data);
// Finds Target for |location_in_root|, including the FrameSinkId of the
// target, updated location in the coordinate system of the target and
// hit-test flags for the target.
// Assumptions about the AggregatedHitTestRegion list received.
// 1. The list is in ascending (front to back) z-order.
// 2. Children count includes children of children.
// 3. After applying transform to the incoming point, point is in the same
// coordinate system as the bounds it is comparing against. We shouldn't
// need to apply rect's origin offset as it should be included in this
// transform.
// For example,
// +e-------------+
// | +c---------|
// | 1 |+a--+ |
// | || 2 | |
// | |+b--------|
// | || |
// | || 3 |
// +--------------+
// In this case, after applying identity transform, 1 is in the coordinate
// system of e; apply the transfrom-from-e-to-c and transform-from-c-to-a
// then we get 2 in the coordinate system of a; apply the
// transfrom-from-e-to-c and transform-from-c-to-b then we get 3 in the
// coordinate system of b.
Target FindTargetForLocation(EventSource event_source,
const gfx::PointF& location_in_root) const;
// Same as FindTargetForLocation(), but starts from |frame_sink_id|.
// |location| is in the coordinate space of |frame_sink_id|. Returns an empty
// target if |frame_sink_id| is not found.
Target FindTargetForLocationStartingFrom(
EventSource event_source,
const gfx::PointF& location,
const FrameSinkId& frame_sink_id) const;
// When a target window is already known, e.g. capture/latched window, convert
// |location_in_root| to be in the coordinate space of the target and store
// that in |transformed_location|. Return true if the transform is successful
// and false otherwise.
// |target_ancestors| contains the FrameSinkId from target to root.
// |target_ancestors.front()| is the target, and |target_ancestors.back()|
// is the root.
bool TransformLocationForTarget(
const std::vector<FrameSinkId>& target_ancestors,
const gfx::PointF& location_in_root,
gfx::PointF* transformed_location) const;
// Gets the transform from root to |target| in physical pixels. Returns true
// and stores the result into |transform| if successful, returns false
// otherwise. This is potentially a little more expensive than
// TransformLocationForTarget(). So if the path from root to target is known,
// then that is the preferred API.
bool GetTransformToTarget(const FrameSinkId& target,
gfx::Transform* transform) const;
// Returns whether client has submitted hit test data for |frame_sink_id|.
// Note that this returns false even if the embedder has submitted hit-test
// data for |frame_sink_id|.
bool ContainsActiveFrameSinkId(const FrameSinkId& frame_sink_id) const;
// Returns hit-test data, using indentation to visualize the tree structure.
std::string PrintHitTestData() const;
const std::vector<AggregatedHitTestRegion>& GetHitTestData() const {
return hit_test_data_;
}
// Returns true if |id| is present in |hit_test_data|. If |id| is present
// |index| is set accordingly.
bool FindIndexOfFrameSink(const FrameSinkId& id, size_t* index) const;
protected:
// The FindTargetForLocation() functions call into this.
// If |is_location_relative_to_parent| is true, |location| is relative to
// the parent, otherwise it is in the coordinate space of |frame_sink_id|.
// Virtual for testing.
virtual Target FindTargetForLocationStartingFromImpl(
EventSource event_source,
const gfx::PointF& location,
const FrameSinkId& frame_sink_id,
bool is_location_relative_to_parent) const;
private:
// Helper function to find |target| for |location| in the |region_index|,
// returns true if a target is found and false otherwise. If
// |is_location_relative_to_parent| is true, |location| is in the coordinate
// space of |region_index|'s parent, otherwise it is in the coordinate space
// of |region_index|.
bool FindTargetInRegionForLocation(EventSource event_source,
const gfx::PointF& location,
size_t region_index,
bool is_location_relative_to_parent,
const FrameSinkId& root_view_frame_sink_id,
Target* target) const;
// Transform |location_in_target| to be in |region_index|'s coordinate space.
// |location_in_target| is in the coordinate space of |region_index|'s parent
// at the beginning.
bool TransformLocationForTargetRecursively(
const std::vector<FrameSinkId>& target_ancestors,
size_t target_ancestor,
size_t region_index,
gfx::PointF* location_in_target) const;
bool GetTransformToTargetRecursively(const FrameSinkId& target,
size_t region_index,
gfx::Transform* transform) const;
// Returns updated aggregated hit test data from stored `hit_test_data` in the
// browser and uses `provider_` to get updated hit test data on VizCompositor
// thread.
const std::vector<AggregatedHitTestRegion>& GetHitTestRegionData() const;
std::vector<AggregatedHitTestRegion> hit_test_data_;
// DataProvider is expected to outlive |this|. `HitTestAggregator` is the
// provider on VizCompositorThread whereas it's null on CrBrowserMain.
std::optional<base::SafeRef<DataProvider>> provider_;
};
} // namespace viz
#endif // COMPONENTS_VIZ_COMMON_HIT_TEST_HIT_TEST_QUERY_H_
|