Merge "Guard against GestureEventProcessor access after Core destruction" into devel...
[platform/core/uifw/dali-core.git] / dali / internal / event / events / gesture-detector-impl.cpp
1 /*
2  * Copyright (c) 2014 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/events/actor-gesture-data.h>
27 #include <dali/internal/event/events/gesture-event-processor.h>
28 #include <dali/internal/event/common/thread-local-storage.h>
29 #include <dali/internal/event/common/stage-impl.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 GestureDetector::GestureDetector(Gesture::Type type)
38 : mType(type),
39   mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
40 {
41 }
42
43 GestureDetector::~GestureDetector()
44 {
45   if ( !mAttachedActors.empty() )
46   {
47     for ( GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter )
48     {
49       Actor* actor( *iter );
50       actor->RemoveObserver( *this );
51       actor->GetGestureData().RemoveGestureDetector( *this );
52     }
53
54     mAttachedActors.clear();
55
56     // Guard to allow handle destruction after Core has been destroyed
57     if ( Stage::IsInstalled() )
58     {
59       mGestureEventProcessor.RemoveGestureDetector( this );
60     }
61   }
62 }
63
64 void GestureDetector::Attach(Actor& actor)
65 {
66   if ( !IsAttached(actor) )
67   {
68     // Register with EventProcessor if first actor being added
69     if ( mAttachedActors.empty() )
70     {
71       mGestureEventProcessor.AddGestureDetector(this);
72     }
73
74     mAttachedActors.push_back(&actor);
75
76     // We need to observe the actor's destruction
77     actor.AddObserver(*this);
78
79     // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
80     actor.GetGestureData().AddGestureDetector( *this );
81
82     // Notification for derived classes
83     OnActorAttach(actor);
84   }
85 }
86
87 void GestureDetector::Detach(Actor& actor)
88 {
89   if ( !mAttachedActors.empty() )
90   {
91     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
92
93     if ( match != mAttachedActors.end() )
94     {
95       // We no longer need to observe the actor's destruction
96       actor.RemoveObserver(*this);
97
98       // Remove detector from actor-gesture-data
99       actor.GetGestureData().RemoveGestureDetector( *this );
100
101       mAttachedActors.erase(match);
102
103       // Notification for derived classes
104       OnActorDetach(actor);
105
106       // Unregister from gesture event processor if we do not have any actors
107       if ( mAttachedActors.empty() )
108       {
109         // Guard to allow handle destruction after Core has been destroyed
110         if( Stage::IsInstalled() )
111         {
112           mGestureEventProcessor.RemoveGestureDetector(this);
113         }
114       }
115     }
116   }
117 }
118
119 void GestureDetector::DetachAll()
120 {
121   if ( !mAttachedActors.empty() )
122   {
123     GestureDetectorActorContainer attachedActors(mAttachedActors);
124
125     // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
126     mAttachedActors.clear();
127
128     for ( GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter )
129     {
130       Actor* actor(*iter);
131
132       // We no longer need to observe the actor's destruction
133       actor->RemoveObserver(*this);
134
135       // Remove detector from actor-gesture-data
136       actor->GetGestureData().RemoveGestureDetector( *this );
137
138       // Notification for derived classes
139       OnActorDetach(*actor);
140     }
141
142     // Guard to allow handle destruction after Core has been destroyed
143     if ( Stage::IsInstalled() )
144     {
145       // Unregister from gesture event processor
146       mGestureEventProcessor.RemoveGestureDetector(this);
147     }
148   }
149 }
150
151 size_t GestureDetector::GetAttachedActorCount() const
152 {
153   return mAttachedActors.size();
154 }
155
156 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
157 {
158   Dali::Actor actor;
159
160   if( index < mAttachedActors.size() )
161   {
162     actor = Dali::Actor( mAttachedActors[index] );
163   }
164
165   return actor;
166 }
167
168 bool GestureDetector::IsAttached(Actor& actor) const
169 {
170   return find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end();
171 }
172
173 void GestureDetector::ObjectDestroyed(Object& object)
174 {
175   if ( !mAttachedActors.empty() )
176   {
177     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
178
179     if ( match != mAttachedActors.end() )
180     {
181       mAttachedActors.erase(match);
182
183       // Notification for derived classes
184       OnActorDestroyed(object);
185
186       // Unregister from gesture event processor if we do not have any actors
187       if ( mAttachedActors.empty() )
188       {
189         // Guard to allow handle destruction after Core has been destroyed
190         if ( Stage::IsInstalled() )
191         {
192           mGestureEventProcessor.RemoveGestureDetector(this);
193         }
194       }
195     }
196   }
197 }
198
199 unsigned int GestureDetector::GetDefaultPropertyCount() const
200 {
201   return 0;
202 }
203
204 void GestureDetector::GetDefaultPropertyIndices( Property::IndexContainer& ) const
205 {
206 }
207
208 const char* GestureDetector::GetDefaultPropertyName( Property::Index index ) const
209 {
210   return NULL;
211 }
212
213 Property::Index GestureDetector::GetDefaultPropertyIndex(const std::string& name) const
214 {
215   return 0;
216 }
217
218 bool GestureDetector::IsDefaultPropertyWritable(Property::Index index) const
219 {
220   return false;
221 }
222
223 bool GestureDetector::IsDefaultPropertyAnimatable(Property::Index index) const
224 {
225   return false;
226 }
227
228 bool GestureDetector::IsDefaultPropertyAConstraintInput( Property::Index index ) const
229 {
230   return false;
231 }
232
233 Property::Type GestureDetector::GetDefaultPropertyType(Property::Index index) const
234 {
235   return Property::NONE;
236 }
237
238 void GestureDetector::SetDefaultProperty( Property::Index index, const Property::Value& property )
239 {
240   // None of our properties should be settable from Public API
241 }
242
243 Property::Value GestureDetector::GetDefaultProperty(Property::Index index) const
244 {
245   return Property::Value();
246 }
247
248 const SceneGraph::PropertyOwner* GestureDetector::GetSceneObject() const
249 {
250   return NULL;
251 }
252
253 const SceneGraph::PropertyBase* GestureDetector::GetSceneObjectAnimatableProperty( Property::Index index ) const
254 {
255   return NULL;
256 }
257
258 const PropertyInputImpl* GestureDetector::GetSceneObjectInputProperty( Property::Index index ) const
259 {
260   return NULL;
261 }
262
263 } // namespace Internal
264
265 } // namespace Dali