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