[dali_2.3.6] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / events / gesture-detector-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/events/gesture-detector-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/event/common/thread-local-storage.h>
28 #include <dali/internal/event/events/actor-gesture-data.h>
29 #include <dali/internal/event/events/gesture-event-processor.h>
30 #include <dali/internal/event/events/touch-event-impl.h>
31 #include <dali/internal/event/render-tasks/render-task-impl.h>
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37 GestureDetector::GestureDetector(GestureType::Value type, const SceneGraph::PropertyOwner* sceneObject)
38 : Object(sceneObject),
39   mType(type),
40   mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
41 {
42 }
43
44 GestureDetector::~GestureDetector()
45 {
46   if(!mPendingAttachActors.empty())
47   {
48     for(GestureDetectorActorContainer::iterator iter = mPendingAttachActors.begin(), endIter = mPendingAttachActors.end(); iter != endIter; ++iter)
49     {
50       Actor* actor(*iter);
51       actor->RemoveObserver(*this);
52       actor->GetGestureData().RemoveGestureDetector(*this);
53     }
54
55     mPendingAttachActors.clear();
56   }
57
58   if(!mAttachedActors.empty())
59   {
60     for(GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter)
61     {
62       Actor* actor(*iter);
63       actor->RemoveObserver(*this);
64       actor->GetGestureData().RemoveGestureDetector(*this);
65     }
66
67     mAttachedActors.clear();
68
69     // Guard to allow handle destruction after Core has been destroyed
70     if(Stage::IsInstalled())
71     {
72       mGestureEventProcessor.RemoveGestureDetector(this);
73     }
74   }
75 }
76
77 void GestureDetector::Attach(Actor& actor)
78 {
79   if(!IsAttached(actor))
80   {
81     if(actor.OnScene())
82     {
83       // Register with EventProcessor if first actor being added
84       if(mAttachedActors.empty())
85       {
86         mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
87       }
88       mAttachedActors.push_back(&actor);
89       // We need to observe the actor's destruction
90       actor.AddObserver(*this);
91       // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
92       actor.GetGestureData().AddGestureDetector(*this);
93       // Notification for derived classes
94       OnActorAttach(actor);
95     }
96     else
97     {
98       actor.AddObserver(*this);
99       // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
100       actor.GetGestureData().AddGestureDetector(*this);
101
102       mPendingAttachActors.push_back(&actor);
103     }
104   }
105 }
106
107 void GestureDetector::SceneObjectAdded(Object& object)
108 {
109   Actor& actor = dynamic_cast<Actor&>(object);
110
111   // Make sure the actor has not already been attached. Can't use IsAttached() as that checks the pending list as well
112   if(find(mAttachedActors.begin(), mAttachedActors.end(), &actor) == mAttachedActors.end())
113   {
114     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
115
116     if(match != mPendingAttachActors.end())
117     {
118       mPendingAttachActors.erase(match);
119
120       // Register with EventProcessor if first actor being added
121       if(mAttachedActors.empty())
122       {
123         mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
124       }
125       mAttachedActors.push_back(&actor);
126
127       // Notification for derived classes
128       OnActorAttach(actor);
129     }
130     else
131     {
132       // Actor was not in the pending list
133       DALI_ASSERT_DEBUG(false);
134     }
135   }
136   else
137   {
138     // Check if actor has been attached and is still in the pending list - this would not be correct
139     DALI_ASSERT_DEBUG(find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) == mPendingAttachActors.end());
140   }
141 }
142
143 void GestureDetector::Detach(Actor& actor)
144 {
145   if(!mPendingAttachActors.empty())
146   {
147     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
148
149     if(match != mPendingAttachActors.end())
150     {
151       // We no longer need to observe the actor's destruction
152       actor.RemoveObserver(*this);
153
154       // Remove detector from actor-gesture-data
155       actor.GetGestureData().RemoveGestureDetector(*this);
156
157       mPendingAttachActors.erase(match);
158     }
159   }
160
161   if(!mAttachedActors.empty())
162   {
163     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
164
165     if(match != mAttachedActors.end())
166     {
167       // We no longer need to observe the actor's destruction
168       actor.RemoveObserver(*this);
169
170       // Remove detector from actor-gesture-data
171       actor.GetGestureData().RemoveGestureDetector(*this);
172
173       mAttachedActors.erase(match);
174
175       // Notification for derived classes
176       OnActorDetach(actor);
177
178       // Unregister from gesture event processor if we do not have any actors
179       if(mAttachedActors.empty())
180       {
181         // Guard to allow handle destruction after Core has been destroyed
182         if(Stage::IsInstalled())
183         {
184           mGestureEventProcessor.RemoveGestureDetector(this);
185         }
186       }
187     }
188   }
189 }
190
191 void GestureDetector::DetachAll()
192 {
193   if(!mPendingAttachActors.empty())
194   {
195     GestureDetectorActorContainer pendingActors(mPendingAttachActors);
196
197     mPendingAttachActors.clear();
198
199     for(GestureDetectorActorContainer::iterator iter = pendingActors.begin(), endIter = pendingActors.end(); iter != endIter; ++iter)
200     {
201       Actor* actor(*iter);
202
203       // We no longer need to observe the actor's destruction
204       actor->RemoveObserver(*this);
205
206       // Remove detector from actor-gesture-data
207       actor->GetGestureData().RemoveGestureDetector(*this);
208     }
209   }
210
211   if(!mAttachedActors.empty())
212   {
213     GestureDetectorActorContainer attachedActors(mAttachedActors);
214
215     // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
216     mAttachedActors.clear();
217
218     for(GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter)
219     {
220       Actor* actor(*iter);
221
222       // We no longer need to observe the actor's destruction
223       actor->RemoveObserver(*this);
224
225       // Remove detector from actor-gesture-data
226       actor->GetGestureData().RemoveGestureDetector(*this);
227
228       // Notification for derived classes
229       OnActorDetach(*actor);
230     }
231
232     // Guard to allow handle destruction after Core has been destroyed
233     if(Stage::IsInstalled())
234     {
235       // Unregister from gesture event processor
236       mGestureEventProcessor.RemoveGestureDetector(this);
237     }
238   }
239 }
240
241 size_t GestureDetector::GetAttachedActorCount() const
242 {
243   return mPendingAttachActors.size() + mAttachedActors.size();
244 }
245
246 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
247 {
248   Dali::Actor actor;
249
250   if(index < mPendingAttachActors.size())
251   {
252     actor = Dali::Actor(mPendingAttachActors[index]);
253   }
254   else if(index < mPendingAttachActors.size() + mAttachedActors.size())
255   {
256     actor = Dali::Actor(mAttachedActors[index - mPendingAttachActors.size()]);
257   }
258
259   return actor;
260 }
261
262 bool GestureDetector::FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch)
263 {
264   bool ret = false;
265   if(touch.GetPointCount() > 0)
266   {
267     const PointState::Type state = touch.GetState(0);
268     Dali::Internal::Actor& actorImpl(GetImplementation(actor));
269     if(state == PointState::DOWN)
270     {
271       Attach(actorImpl);
272     }
273
274     Integration::TouchEvent touchEvent(touch.GetTime());
275     for(std::size_t i = 0; i< touch.GetPointCount(); i++)
276     {
277       Integration::Point      point;
278       point.SetState(touch.GetState(i));
279       point.SetDeviceId(touch.GetDeviceId(i));
280       point.SetScreenPosition(touch.GetScreenPosition(i));
281       point.SetRadius(touch.GetRadius(i));
282       point.SetPressure(touch.GetPressure(i));
283       point.SetAngle(touch.GetAngle(i));
284       point.SetDeviceClass(touch.GetDeviceClass(i));
285       point.SetDeviceSubclass(touch.GetDeviceSubclass(i));
286       point.SetMouseButton(touch.GetMouseButton(i));
287       point.SetHitActor(touch.GetHitActor(i));
288       point.SetLocalPosition(touch.GetLocalPosition(i));
289       touchEvent.points.push_back(point);
290     }
291
292     Dali::Internal::TouchEvent& touchEventImpl(GetImplementation(touch));
293     mGestureEventProcessor.ProcessTouchEvent(this, actorImpl, GetImplementation(touchEventImpl.GetRenderTaskPtr()), actorImpl.GetScene(), touchEvent);
294
295     if(state == PointState::FINISHED || state == PointState::INTERRUPTED || state == PointState::LEAVE)
296     {
297       Detach(actorImpl);
298     }
299     ret = true;
300   }
301   return ret;
302 }
303
304 bool GestureDetector::IsAttached(Actor& actor) const
305 {
306   return (find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end()) ||
307          (find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end());
308 }
309
310 void GestureDetector::ObjectDestroyed(Object& object)
311 {
312   if(!mPendingAttachActors.empty())
313   {
314     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &object);
315
316     if(match != mPendingAttachActors.end())
317     {
318       mPendingAttachActors.erase(match);
319     }
320   }
321
322   if(!mAttachedActors.empty())
323   {
324     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
325
326     if(match != mAttachedActors.end())
327     {
328       mAttachedActors.erase(match);
329
330       // Notification for derived classes
331       OnActorDestroyed(object);
332
333       // Unregister from gesture event processor if we do not have any actors
334       if(mAttachedActors.empty())
335       {
336         // Guard to allow handle destruction after Core has been destroyed
337         if(Stage::IsInstalled())
338         {
339           mGestureEventProcessor.RemoveGestureDetector(this);
340         }
341       }
342     }
343   }
344 }
345
346 } // namespace Internal
347
348 } // namespace Dali