1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set sw=2 ts=8 et tw=80 : */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_layers_HitTestingTreeNode_h 8 #define mozilla_layers_HitTestingTreeNode_h 9 10 #include "APZUtils.h" // for HitTestResult 11 #include "FrameMetrics.h" // for ScrollableLayerGuid 12 #include "Layers.h" 13 #include "mozilla/gfx/Matrix.h" // for Matrix4x4 14 #include "mozilla/layers/LayersTypes.h" // for EventRegions 15 #include "mozilla/Maybe.h" // for Maybe 16 #include "mozilla/RefPtr.h" // for nsRefPtr 17 18 namespace mozilla { 19 namespace layers { 20 21 class AsyncDragMetrics; 22 class AsyncPanZoomController; 23 24 /** 25 * This class represents a node in a tree that is used by the APZCTreeManager 26 * to do hit testing. The tree is roughly a copy of the layer tree, but will 27 * contain multiple nodes in cases where the layer has multiple FrameMetrics. 28 * In other words, the structure of this tree should be identical to the 29 * LayerMetrics tree (see documentation in LayerMetricsWrapper.h). 30 * 31 * Not all HitTestingTreeNode instances will have an APZC associated with them; 32 * only HitTestingTreeNodes that correspond to layers with scrollable metrics 33 * have APZCs. 34 * Multiple HitTestingTreeNode instances may share the same underlying APZC 35 * instance if the layers they represent share the same scrollable metrics (i.e. 36 * are part of the same animated geometry root). If this happens, exactly one of 37 * the HitTestingTreeNode instances will be designated as the "primary holder" 38 * of the APZC. When this primary holder is destroyed, it will destroy the APZC 39 * along with it; in contrast, destroying non-primary-holder nodes will not 40 * destroy the APZC. 41 * Code should not make assumptions about which of the nodes will be the 42 * primary holder, only that that there will be exactly one for each APZC in 43 * the tree. 44 * 45 * The reason this tree exists at all is so that we can do hit-testing on the 46 * thread that we receive input on (referred to the as the controller thread in 47 * APZ terminology), which may be different from the compositor thread. 48 * Accessing the compositor layer tree can only be done on the compositor 49 * thread, and so it is simpler to make a copy of the hit-testing related 50 * properties into a separate tree. 51 */ 52 class HitTestingTreeNode { 53 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(HitTestingTreeNode); 54 55 private: 56 ~HitTestingTreeNode(); 57 public: 58 HitTestingTreeNode(AsyncPanZoomController* aApzc, bool aIsPrimaryHolder, 59 uint64_t aLayersId); 60 void RecycleWith(AsyncPanZoomController* aApzc, uint64_t aLayersId); 61 void Destroy(); 62 63 /* Tree construction methods */ 64 65 void SetLastChild(HitTestingTreeNode* aChild); 66 void SetPrevSibling(HitTestingTreeNode* aSibling); 67 void MakeRoot(); 68 69 /* Tree walking methods. GetFirstChild is O(n) in the number of children. The 70 * other tree walking methods are all O(1). */ 71 72 HitTestingTreeNode* GetFirstChild() const; 73 HitTestingTreeNode* GetLastChild() const; 74 HitTestingTreeNode* GetPrevSibling() const; 75 HitTestingTreeNode* GetParent() const; 76 77 /* APZC related methods */ 78 79 AsyncPanZoomController* GetApzc() const; 80 AsyncPanZoomController* GetNearestContainingApzc() const; 81 bool IsPrimaryHolder() const; 82 uint64_t GetLayersId() const; 83 84 /* Hit test related methods */ 85 86 void SetHitTestData(const EventRegions& aRegions, 87 const CSSTransformMatrix& aTransform, 88 const Maybe<ParentLayerIntRegion>& aClipRegion, 89 const EventRegionsOverride& aOverride); 90 bool IsOutsideClip(const ParentLayerPoint& aPoint) const; 91 92 /* Scrollbar info */ 93 94 void SetScrollbarData(FrameMetrics::ViewID aScrollViewId, 95 Layer::ScrollDirection aDir, 96 int32_t aScrollSize, 97 bool aIsScrollContainer); 98 bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const; 99 int32_t GetScrollSize() const; 100 bool IsScrollbarNode() const; 101 102 /* Fixed pos info */ 103 104 void SetFixedPosData(FrameMetrics::ViewID aFixedPosTarget); 105 FrameMetrics::ViewID GetFixedPosTarget() const; 106 107 /* Convert aPoint into the LayerPixel space for the layer corresponding to 108 * this node. */ 109 Maybe<LayerPoint> Untransform(const ParentLayerPoint& aPoint) const; 110 /* Assuming aPoint is inside the clip region for this node, check which of the 111 * event region spaces it falls inside. */ 112 HitTestResult HitTest(const ParentLayerPoint& aPoint) const; 113 /* Returns the mOverride flag. */ 114 EventRegionsOverride GetEventRegionsOverride() const; 115 116 /* Debug helpers */ 117 void Dump(const char* aPrefix = "") const; 118 119 private: 120 void SetApzcParent(AsyncPanZoomController* aApzc); 121 122 RefPtr<HitTestingTreeNode> mLastChild; 123 RefPtr<HitTestingTreeNode> mPrevSibling; 124 RefPtr<HitTestingTreeNode> mParent; 125 126 RefPtr<AsyncPanZoomController> mApzc; 127 bool mIsPrimaryApzcHolder; 128 129 uint64_t mLayersId; 130 131 FrameMetrics::ViewID mScrollViewId; 132 Layer::ScrollDirection mScrollDir; 133 int32_t mScrollSize; 134 bool mIsScrollbarContainer; 135 136 FrameMetrics::ViewID mFixedPosTarget; 137 138 /* Let {L,M} be the {layer, scrollable metrics} pair that this node 139 * corresponds to in the layer tree. mEventRegions contains the event regions 140 * from L, in the case where event-regions are enabled. If event-regions are 141 * disabled, it will contain the visible region of L, which we use as an 142 * approximation to the hit region for the purposes of obscuring other layers. 143 * This value is in L's LayerPixels. 144 */ 145 EventRegions mEventRegions; 146 147 /* This is the transform from layer L. This does NOT include any async 148 * transforms. */ 149 CSSTransformMatrix mTransform; 150 151 /* This is clip rect for L that we wish to use for hit-testing purposes. Note 152 * that this may not be exactly the same as the clip rect on layer L because 153 * of the touch-sensitive region provided by the GeckoContentController, or 154 * because we may use the composition bounds of the layer if the clip is not 155 * present. This value is in L's ParentLayerPixels. */ 156 Maybe<ParentLayerIntRegion> mClipRegion; 157 158 /* Indicates whether or not the event regions on this node need to be 159 * overridden in a certain way. */ 160 EventRegionsOverride mOverride; 161 }; 162 163 } // namespace layers 164 } // namespace mozilla 165 166 #endif // mozilla_layers_HitTestingTreeNode_h 167