2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/events/gesture-detector-impl.h>
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>
37 GestureDetector::GestureDetector(GestureType::Value type, const SceneGraph::PropertyOwner* sceneObject)
38 : Object(sceneObject),
40 mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
44 GestureDetector::~GestureDetector()
46 if(!mPendingAttachActors.empty())
48 for(GestureDetectorActorContainer::iterator iter = mPendingAttachActors.begin(), endIter = mPendingAttachActors.end(); iter != endIter; ++iter)
51 actor->RemoveObserver(*this);
52 actor->GetGestureData().RemoveGestureDetector(*this);
55 mPendingAttachActors.clear();
58 if(!mAttachedActors.empty())
60 for(GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter)
63 actor->RemoveObserver(*this);
64 actor->GetGestureData().RemoveGestureDetector(*this);
67 mAttachedActors.clear();
69 // Guard to allow handle destruction after Core has been destroyed
70 if(Stage::IsInstalled())
72 mGestureEventProcessor.RemoveGestureDetector(this);
77 void GestureDetector::Attach(Actor& actor)
79 if(!IsAttached(actor))
83 // Register with EventProcessor if first actor being added
84 if(mAttachedActors.empty())
86 mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
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
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);
102 mPendingAttachActors.push_back(&actor);
107 void GestureDetector::SceneObjectAdded(Object& object)
109 Actor& actor = dynamic_cast<Actor&>(object);
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())
114 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
116 if(match != mPendingAttachActors.end())
118 mPendingAttachActors.erase(match);
120 // Register with EventProcessor if first actor being added
121 if(mAttachedActors.empty())
123 mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
125 mAttachedActors.push_back(&actor);
127 // Notification for derived classes
128 OnActorAttach(actor);
132 // Actor was not in the pending list
133 DALI_ASSERT_DEBUG(false);
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());
143 void GestureDetector::Detach(Actor& actor)
145 if(!mPendingAttachActors.empty())
147 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
149 if(match != mPendingAttachActors.end())
151 // We no longer need to observe the actor's destruction
152 actor.RemoveObserver(*this);
154 // Remove detector from actor-gesture-data
155 actor.GetGestureData().RemoveGestureDetector(*this);
157 mPendingAttachActors.erase(match);
161 if(!mAttachedActors.empty())
163 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
165 if(match != mAttachedActors.end())
167 // We no longer need to observe the actor's destruction
168 actor.RemoveObserver(*this);
170 // Remove detector from actor-gesture-data
171 actor.GetGestureData().RemoveGestureDetector(*this);
173 mAttachedActors.erase(match);
175 // Notification for derived classes
176 OnActorDetach(actor);
178 // Unregister from gesture event processor if we do not have any actors
179 if(mAttachedActors.empty())
181 // Guard to allow handle destruction after Core has been destroyed
182 if(Stage::IsInstalled())
184 mGestureEventProcessor.RemoveGestureDetector(this);
191 void GestureDetector::DetachAll()
193 if(!mPendingAttachActors.empty())
195 GestureDetectorActorContainer pendingActors(mPendingAttachActors);
197 mPendingAttachActors.clear();
199 for(GestureDetectorActorContainer::iterator iter = pendingActors.begin(), endIter = pendingActors.end(); iter != endIter; ++iter)
203 // We no longer need to observe the actor's destruction
204 actor->RemoveObserver(*this);
206 // Remove detector from actor-gesture-data
207 actor->GetGestureData().RemoveGestureDetector(*this);
211 if(!mAttachedActors.empty())
213 GestureDetectorActorContainer attachedActors(mAttachedActors);
215 // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
216 mAttachedActors.clear();
218 for(GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter)
222 // We no longer need to observe the actor's destruction
223 actor->RemoveObserver(*this);
225 // Remove detector from actor-gesture-data
226 actor->GetGestureData().RemoveGestureDetector(*this);
228 // Notification for derived classes
229 OnActorDetach(*actor);
232 // Guard to allow handle destruction after Core has been destroyed
233 if(Stage::IsInstalled())
235 // Unregister from gesture event processor
236 mGestureEventProcessor.RemoveGestureDetector(this);
241 size_t GestureDetector::GetAttachedActorCount() const
243 return mPendingAttachActors.size() + mAttachedActors.size();
246 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
250 if(index < mPendingAttachActors.size())
252 actor = Dali::Actor(mPendingAttachActors[index]);
254 else if(index < mPendingAttachActors.size() + mAttachedActors.size())
256 actor = Dali::Actor(mAttachedActors[index - mPendingAttachActors.size()]);
262 bool GestureDetector::FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch)
265 if(touch.GetPointCount() > 0)
267 const PointState::Type state = touch.GetState(0);
268 Dali::Internal::Actor& actorImpl(GetImplementation(actor));
269 if(state == PointState::DOWN)
274 Integration::TouchEvent touchEvent(touch.GetTime());
275 for(std::size_t i = 0; i< touch.GetPointCount(); i++)
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);
292 Dali::Internal::TouchEvent& touchEventImpl(GetImplementation(touch));
293 mGestureEventProcessor.ProcessTouchEvent(this, actorImpl, GetImplementation(touchEventImpl.GetRenderTaskPtr()), actorImpl.GetScene(), touchEvent);
295 if(state == PointState::FINISHED || state == PointState::INTERRUPTED || state == PointState::LEAVE)
304 bool GestureDetector::IsAttached(Actor& actor) const
306 return (find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end()) ||
307 (find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end());
310 void GestureDetector::ObjectDestroyed(Object& object)
312 if(!mPendingAttachActors.empty())
314 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &object);
316 if(match != mPendingAttachActors.end())
318 mPendingAttachActors.erase(match);
322 if(!mAttachedActors.empty())
324 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
326 if(match != mAttachedActors.end())
328 mAttachedActors.erase(match);
330 // Notification for derived classes
331 OnActorDestroyed(object);
333 // Unregister from gesture event processor if we do not have any actors
334 if(mAttachedActors.empty())
336 // Guard to allow handle destruction after Core has been destroyed
337 if(Stage::IsInstalled())
339 mGestureEventProcessor.RemoveGestureDetector(this);
346 } // namespace Internal