[dali_2.3.33] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / events / gesture-detector-impl.cpp
1 /*
2  * Copyright (c) 2024 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   mFeededActor(),
42   mRenderTask(nullptr),
43   mGestureRecognizer(),
44   mIsDetected(false)
45 {
46 }
47
48 GestureDetector::~GestureDetector()
49 {
50   if(DALI_UNLIKELY(!Dali::Stage::IsCoreThread()))
51   {
52     DALI_LOG_ERROR("~GestureDetector[%p] called from non-UI thread! something unknown issue will be happened!\n", this);
53   }
54
55   if(!mPendingAttachActors.empty())
56   {
57     for(GestureDetectorActorContainer::iterator iter = mPendingAttachActors.begin(), endIter = mPendingAttachActors.end(); iter != endIter; ++iter)
58     {
59       Actor* actor(*iter);
60       actor->RemoveObserver(*this);
61       actor->GetGestureData().RemoveGestureDetector(*this);
62     }
63
64     mPendingAttachActors.clear();
65   }
66
67   if(!mAttachedActors.empty())
68   {
69     for(GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter)
70     {
71       Actor* actor(*iter);
72       actor->RemoveObserver(*this);
73       actor->GetGestureData().RemoveGestureDetector(*this);
74     }
75
76     mAttachedActors.clear();
77
78     // Guard to allow handle destruction after Core has been destroyed
79     if(Stage::IsInstalled())
80     {
81       mGestureEventProcessor.RemoveGestureDetector(this);
82     }
83   }
84 }
85
86 void GestureDetector::Attach(Actor& actor)
87 {
88   if(!IsAttached(actor))
89   {
90     if(actor.OnScene())
91     {
92       // Register with EventProcessor if first actor being added
93       if(mAttachedActors.empty())
94       {
95         mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
96       }
97       mAttachedActors.push_back(&actor);
98       // We need to observe the actor's destruction
99       actor.AddObserver(*this);
100       // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
101       actor.GetGestureData().AddGestureDetector(*this);
102       // Notification for derived classes
103       OnActorAttach(actor);
104     }
105     else
106     {
107       actor.AddObserver(*this);
108       // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
109       actor.GetGestureData().AddGestureDetector(*this);
110
111       mPendingAttachActors.push_back(&actor);
112     }
113   }
114 }
115
116 void GestureDetector::SceneObjectAdded(Object& object)
117 {
118   Actor& actor = dynamic_cast<Actor&>(object);
119
120   // Make sure the actor has not already been attached. Can't use IsAttached() as that checks the pending list as well
121   if(find(mAttachedActors.begin(), mAttachedActors.end(), &actor) == mAttachedActors.end())
122   {
123     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
124
125     if(match != mPendingAttachActors.end())
126     {
127       mPendingAttachActors.erase(match);
128
129       // Register with EventProcessor if first actor being added
130       if(mAttachedActors.empty())
131       {
132         mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
133       }
134       mAttachedActors.push_back(&actor);
135
136       // Notification for derived classes
137       OnActorAttach(actor);
138     }
139     else
140     {
141       // Actor was not in the pending list
142       DALI_ASSERT_DEBUG(false);
143     }
144   }
145   else
146   {
147     // Check if actor has been attached and is still in the pending list - this would not be correct
148     DALI_ASSERT_DEBUG(find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) == mPendingAttachActors.end());
149   }
150 }
151
152 void GestureDetector::Detach(Actor& actor)
153 {
154   if(!mPendingAttachActors.empty())
155   {
156     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
157
158     if(match != mPendingAttachActors.end())
159     {
160       // We no longer need to observe the actor's destruction
161       actor.RemoveObserver(*this);
162
163       // Remove detector from actor-gesture-data
164       actor.GetGestureData().RemoveGestureDetector(*this);
165
166       mPendingAttachActors.erase(match);
167     }
168   }
169
170   if(!mAttachedActors.empty())
171   {
172     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
173
174     if(match != mAttachedActors.end())
175     {
176       // We no longer need to observe the actor's destruction
177       actor.RemoveObserver(*this);
178
179       // Remove detector from actor-gesture-data
180       actor.GetGestureData().RemoveGestureDetector(*this);
181
182       mAttachedActors.erase(match);
183
184       // Notification for derived classes
185       OnActorDetach(actor);
186
187       // Unregister from gesture event processor if we do not have any actors
188       if(mAttachedActors.empty())
189       {
190         // Guard to allow handle destruction after Core has been destroyed
191         if(Stage::IsInstalled())
192         {
193           mGestureEventProcessor.RemoveGestureDetector(this);
194         }
195       }
196     }
197   }
198 }
199
200 void GestureDetector::DetachAll()
201 {
202   if(!mPendingAttachActors.empty())
203   {
204     GestureDetectorActorContainer pendingActors(mPendingAttachActors);
205
206     mPendingAttachActors.clear();
207
208     for(GestureDetectorActorContainer::iterator iter = pendingActors.begin(), endIter = pendingActors.end(); iter != endIter; ++iter)
209     {
210       Actor* actor(*iter);
211
212       // We no longer need to observe the actor's destruction
213       actor->RemoveObserver(*this);
214
215       // Remove detector from actor-gesture-data
216       actor->GetGestureData().RemoveGestureDetector(*this);
217     }
218   }
219
220   if(!mAttachedActors.empty())
221   {
222     GestureDetectorActorContainer attachedActors(mAttachedActors);
223
224     // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
225     mAttachedActors.clear();
226
227     for(GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter)
228     {
229       Actor* actor(*iter);
230
231       // We no longer need to observe the actor's destruction
232       actor->RemoveObserver(*this);
233
234       // Remove detector from actor-gesture-data
235       actor->GetGestureData().RemoveGestureDetector(*this);
236
237       // Notification for derived classes
238       OnActorDetach(*actor);
239     }
240
241     // Guard to allow handle destruction after Core has been destroyed
242     if(Stage::IsInstalled())
243     {
244       // Unregister from gesture event processor
245       mGestureEventProcessor.RemoveGestureDetector(this);
246     }
247   }
248 }
249
250 size_t GestureDetector::GetAttachedActorCount() const
251 {
252   return mPendingAttachActors.size() + mAttachedActors.size();
253 }
254
255 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
256 {
257   Dali::Actor actor;
258
259   if(index < mPendingAttachActors.size())
260   {
261     actor = Dali::Actor(mPendingAttachActors[index]);
262   }
263   else if(index < mPendingAttachActors.size() + mAttachedActors.size())
264   {
265     actor = Dali::Actor(mAttachedActors[index - mPendingAttachActors.size()]);
266   }
267
268   return actor;
269 }
270
271 bool GestureDetector::HandleEvent(Dali::Actor& actor, Dali::TouchEvent& touch)
272 {
273   bool                   ret = false;
274   Dali::Internal::Actor& actorImpl(GetImplementation(actor));
275   if(touch.GetPointCount() > 0 && actorImpl.OnScene())
276   {
277     const PointState::Type state = touch.GetState(0);
278     if(state == PointState::DOWN)
279     {
280       CancelProcessing();
281       Clear();
282       actorImpl.SetNeedGesturePropagation(false);
283       mGestureEventProcessor.RegisterGestureDetector(this);
284     }
285
286     Integration::TouchEvent touchEvent(touch.GetTime());
287     for(std::size_t i = 0; i < touch.GetPointCount(); i++)
288     {
289       Integration::Point point;
290       point.SetState(touch.GetState(i));
291       point.SetDeviceId(touch.GetDeviceId(i));
292       point.SetScreenPosition(touch.GetScreenPosition(i));
293       point.SetRadius(touch.GetRadius(i));
294       point.SetPressure(touch.GetPressure(i));
295       point.SetAngle(touch.GetAngle(i));
296       point.SetDeviceClass(touch.GetDeviceClass(i));
297       point.SetDeviceSubclass(touch.GetDeviceSubclass(i));
298       point.SetMouseButton(touch.GetMouseButton(i));
299       point.SetHitActor(touch.GetHitActor(i));
300       point.SetLocalPosition(touch.GetLocalPosition(i));
301       touchEvent.points.push_back(point);
302     }
303
304     Dali::Internal::TouchEvent& touchEventImpl(GetImplementation(touch));
305     mFeededActor.SetActor(&actorImpl);
306     mRenderTask = &GetImplementation(touchEventImpl.GetRenderTaskPtr());
307
308     if(!actorImpl.NeedGesturePropagation())
309     {
310       ProcessTouchEvent(actorImpl.GetScene(), touchEvent);
311     }
312
313     ret = IsDetected() && !actorImpl.NeedGesturePropagation();
314     actorImpl.SetNeedGesturePropagation(false);
315
316     if(state == PointState::FINISHED || state == PointState::INTERRUPTED)
317     {
318       Clear();
319     }
320   }
321   return ret;
322 }
323
324 void GestureDetector::CancelAllOtherGestureDetectors()
325 {
326   mGestureEventProcessor.CancelAllOtherGestureDetectors(this);
327 }
328
329 bool GestureDetector::IsDetected() const
330 {
331   return mIsDetected;
332 }
333
334 void GestureDetector::SetDetected(bool detected)
335 {
336   mIsDetected = detected;
337 }
338
339 void GestureDetector::Clear()
340 {
341   mGestureRecognizer = nullptr;
342   mGestureEventProcessor.UnregisterGestureDetector(this);
343   SetDetected(false);
344 }
345
346 bool GestureDetector::IsAttached(Actor& actor) const
347 {
348   return (find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end()) ||
349          (find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end());
350 }
351
352 void GestureDetector::ObjectDestroyed(Object& object)
353 {
354   if(!mPendingAttachActors.empty())
355   {
356     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &object);
357
358     if(match != mPendingAttachActors.end())
359     {
360       mPendingAttachActors.erase(match);
361     }
362   }
363
364   if(!mAttachedActors.empty())
365   {
366     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
367
368     if(match != mAttachedActors.end())
369     {
370       mAttachedActors.erase(match);
371
372       // Notification for derived classes
373       OnActorDestroyed(object);
374
375       // Unregister from gesture event processor if we do not have any actors
376       if(mAttachedActors.empty())
377       {
378         // Guard to allow handle destruction after Core has been destroyed
379         if(Stage::IsInstalled())
380         {
381           mGestureEventProcessor.RemoveGestureDetector(this);
382         }
383       }
384     }
385   }
386 }
387
388 } // namespace Internal
389
390 } // namespace Dali