Add UserInteractionEnabled property on actor for controlling user interaction.
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / layer-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/actors/layer-impl.h>
20
21 // EXTERNAL INCLUDES
22
23 // INTERNAL INCLUDES
24 #include <dali/public-api/actors/layer.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/object/type-registry.h>
27
28 #include <dali/internal/event/actors/layer-list.h>
29 #include <dali/internal/event/common/event-thread-services.h>
30 #include <dali/internal/event/common/property-helper.h>
31 #include <dali/internal/event/common/scene-impl.h>
32
33 #include <dali/internal/update/manager/update-manager.h>
34 #include <dali/internal/update/nodes/scene-graph-layer.h>
35
36 using Dali::Internal::SceneGraph::UpdateManager;
37
38 namespace Dali
39 {
40 namespace
41 {
42 typedef Layer::Behavior Behavior;
43
44 DALI_ENUM_TO_STRING_TABLE_BEGIN(BEHAVIOR)
45   DALI_ENUM_TO_STRING_WITH_SCOPE(Layer, LAYER_UI)
46   DALI_ENUM_TO_STRING_WITH_SCOPE(Layer, LAYER_3D)
47 DALI_ENUM_TO_STRING_TABLE_END(BEHAVIOR)
48
49 } // namespace
50
51 namespace Internal
52 {
53 namespace
54 {
55 // Properties
56
57 //              Name                Type      writable animatable constraint-input  enum for index-checking
58 DALI_PROPERTY_TABLE_BEGIN
59 DALI_PROPERTY("clippingEnable", BOOLEAN, true, false, true, Dali::Layer::Property::CLIPPING_ENABLE)
60 DALI_PROPERTY("clippingBox", RECTANGLE, true, false, true, Dali::Layer::Property::CLIPPING_BOX)
61 DALI_PROPERTY("behavior", INTEGER, true, false, false, Dali::Layer::Property::BEHAVIOR)
62 DALI_PROPERTY("depth", INTEGER, false, false, false, Dali::Layer::Property::DEPTH)
63 DALI_PROPERTY("depthTest", BOOLEAN, true, false, false, Dali::Layer::Property::DEPTH_TEST)
64 DALI_PROPERTY("consumesTouch", BOOLEAN, true, false, false, Dali::Layer::Property::CONSUMES_TOUCH)
65 DALI_PROPERTY("consumesHover", BOOLEAN, true, false, false, Dali::Layer::Property::CONSUMES_HOVER)
66 DALI_PROPERTY_TABLE_END(DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, LayerDefaultProperties)
67
68 // Actions
69
70 static constexpr std::string_view ACTION_RAISE           = "raise";
71 static constexpr std::string_view ACTION_LOWER           = "lower";
72 static constexpr std::string_view ACTION_RAISE_TO_TOP    = "raiseToTop";
73 static constexpr std::string_view ACTION_LOWER_TO_BOTTOM = "lowerToBottom";
74
75 BaseHandle Create()
76 {
77   return Dali::Layer::New();
78 }
79
80 TypeRegistration mType(typeid(Dali::Layer), typeid(Dali::Actor), Create, LayerDefaultProperties);
81
82 TypeAction a1(mType, std::string(ACTION_RAISE), &Layer::DoAction);
83 TypeAction a2(mType, std::string(ACTION_LOWER), &Layer::DoAction);
84 TypeAction a3(mType, std::string(ACTION_RAISE_TO_TOP), &Layer::DoAction);
85 TypeAction a4(mType, std::string(ACTION_LOWER_TO_BOTTOM), &Layer::DoAction);
86
87 } // unnamed namespace
88
89 LayerPtr Layer::New()
90 {
91   // create node, nodes are owned by UpdateManager
92   SceneGraph::Layer*             layerNode = SceneGraph::Layer::New();
93   OwnerPointer<SceneGraph::Node> transferOwnership(layerNode);
94   AddNodeMessage(EventThreadServices::Get().GetUpdateManager(), transferOwnership);
95   LayerPtr layer(new Layer(Actor::LAYER, *layerNode));
96
97   // Second-phase construction
98   layer->Initialize();
99
100   return layer;
101 }
102
103 LayerPtr Layer::NewRoot(LayerList& layerList)
104 {
105   // create node, nodes are owned by UpdateManager
106   SceneGraph::Layer*              rootLayer = SceneGraph::Layer::New();
107   OwnerPointer<SceneGraph::Layer> transferOwnership(rootLayer);
108   InstallRootMessage(EventThreadServices::Get().GetUpdateManager(), transferOwnership);
109
110   LayerPtr root(new Layer(Actor::ROOT_LAYER, *rootLayer));
111
112   // root actor is immediately considered to be on-stage
113   root->mIsOnScene = true;
114
115   // The root actor will not emit a stage connection signal so set the signalled flag here as well
116   root->mOnSceneSignalled = true;
117
118   // layer-list must be set for the root layer
119   root->mLayerList = &layerList;
120   layerList.SetRootLayer(&(*root));
121   layerList.RegisterLayer(*root);
122
123   return root;
124 }
125
126 Layer::Layer(Actor::DerivedType type, const SceneGraph::Layer& layer)
127 : Actor(type, layer),
128   mLayerList(nullptr),
129   mClippingBox(0, 0, 0, 0),
130   mSortFunction(Layer::ZValue),
131   mBehavior(Dali::Layer::LAYER_UI),
132   mIsClipping(false),
133   mDepthTestDisabled(true),
134   mTouchConsumed(false),
135   mHoverConsumed(false)
136 {
137 }
138
139 void Layer::OnInitialize()
140 {
141 }
142
143 Layer::~Layer()
144 {
145   if(mIsRoot)
146   {
147     // Guard to allow handle destruction after Core has been destroyed
148     if(EventThreadServices::IsCoreRunning())
149     {
150       UninstallRootMessage(GetEventThreadServices().GetUpdateManager(), &GetSceneGraphLayer());
151
152       GetEventThreadServices().UnregisterObject(this);
153     }
154   }
155 }
156
157 unsigned int Layer::GetDepth() const
158 {
159   return mLayerList ? mLayerList->GetDepth(this) : 0u;
160 }
161
162 void Layer::Raise()
163 {
164   if(mLayerList)
165   {
166     mLayerList->RaiseLayer(*this);
167   }
168 }
169
170 void Layer::Lower()
171 {
172   if(mLayerList)
173   {
174     mLayerList->LowerLayer(*this);
175   }
176 }
177
178 void Layer::RaiseAbove(const Internal::Layer& target)
179 {
180   // cannot raise above ourself, both have to be on the scene
181   if((this != &target) && OnScene() && target.OnScene())
182   {
183     // get parameters depth
184     const uint32_t targetDepth = target.GetDepth();
185     if(GetDepth() < targetDepth)
186     {
187       MoveAbove(target);
188     }
189   }
190 }
191
192 void Layer::LowerBelow(const Internal::Layer& target)
193 {
194   // cannot lower below ourself, both have to be on the scene
195   if((this != &target) && OnScene() && target.OnScene())
196   {
197     // get parameters depth
198     const uint32_t targetDepth = target.GetDepth();
199     if(GetDepth() > targetDepth)
200     {
201       MoveBelow(target);
202     }
203   }
204 }
205
206 void Layer::RaiseToTop()
207 {
208   if(mLayerList)
209   {
210     mLayerList->RaiseLayerToTop(*this);
211   }
212 }
213
214 void Layer::LowerToBottom()
215 {
216   if(mLayerList)
217   {
218     mLayerList->LowerLayerToBottom(*this);
219   }
220 }
221
222 void Layer::MoveAbove(const Internal::Layer& target)
223 {
224   // cannot raise above ourself, both have to be on the scene
225   if((this != &target) && mLayerList && target.OnScene())
226   {
227     mLayerList->MoveLayerAbove(*this, target);
228   }
229 }
230
231 void Layer::MoveBelow(const Internal::Layer& target)
232 {
233   // cannot lower below ourself, both have to be on the scene
234   if((this != &target) && mLayerList && target.OnScene())
235   {
236     mLayerList->MoveLayerBelow(*this, target);
237   }
238 }
239
240 void Layer::SetBehavior(Dali::Layer::Behavior behavior)
241 {
242   mBehavior = behavior;
243
244   // Notify update side object.
245   SetBehaviorMessage(GetEventThreadServices(), GetSceneGraphLayer(), behavior);
246   // By default, disable depth test for LAYER_UI, and enable for LAYER_3D.
247   SetDepthTestDisabled(mBehavior == Dali::Layer::LAYER_UI);
248 }
249
250 void Layer::SetClipping(bool enabled)
251 {
252   if(enabled != mIsClipping)
253   {
254     mIsClipping = enabled;
255
256     // layerNode is being used in a separate thread; queue a message to set the value
257     SetClippingMessage(GetEventThreadServices(), GetSceneGraphLayer(), mIsClipping);
258   }
259 }
260
261 void Layer::SetClippingBox(int x, int y, int width, int height)
262 {
263   if((x != mClippingBox.x) ||
264      (y != mClippingBox.y) ||
265      (width != mClippingBox.width) ||
266      (height != mClippingBox.height))
267   {
268     // Clipping box is not animatable; this is the most up-to-date value
269     mClippingBox.Set(x, y, width, height);
270
271     // Convert mClippingBox to GL based coordinates (from bottom-left)
272     ClippingBox clippingBox(mClippingBox);
273
274     if(mScene)
275     {
276       clippingBox.y = static_cast<int32_t>(mScene->GetSize().height) - clippingBox.y - clippingBox.height;
277
278       // layerNode is being used in a separate thread; queue a message to set the value
279       SetClippingBoxMessage(GetEventThreadServices(), GetSceneGraphLayer(), clippingBox);
280     }
281   }
282 }
283
284 void Layer::SetDepthTestDisabled(bool disable)
285 {
286   if(disable != mDepthTestDisabled)
287   {
288     mDepthTestDisabled = disable;
289
290     // Send message.
291     // layerNode is being used in a separate thread; queue a message to set the value
292     SetDepthTestDisabledMessage(GetEventThreadServices(), GetSceneGraphLayer(), mDepthTestDisabled);
293   }
294 }
295
296 bool Layer::IsDepthTestDisabled() const
297 {
298   return mDepthTestDisabled;
299 }
300
301 void Layer::SetSortFunction(Dali::Layer::SortFunctionType function)
302 {
303   if(function != mSortFunction)
304   {
305     mSortFunction = function;
306
307     // layerNode is being used in a separate thread; queue a message to set the value
308     SetSortFunctionMessage(GetEventThreadServices(), GetSceneGraphLayer(), mSortFunction);
309   }
310 }
311
312 void Layer::SetTouchConsumed(bool consume)
313 {
314   mTouchConsumed = consume;
315 }
316
317 bool Layer::IsTouchConsumed() const
318 {
319   return mTouchConsumed;
320 }
321
322 void Layer::SetHoverConsumed(bool consume)
323 {
324   mHoverConsumed = consume;
325 }
326
327 bool Layer::IsHoverConsumed() const
328 {
329   return mHoverConsumed;
330 }
331
332 void Layer::OnSceneConnectionInternal()
333 {
334   if(!mIsRoot)
335   {
336     DALI_ASSERT_DEBUG(NULL == mLayerList);
337
338     // Find the ordered layer-list
339     for(Actor* parent = GetParent(); parent != nullptr; parent = parent->GetParent())
340     {
341       if(parent->IsLayer())
342       {
343         Layer* parentLayer = static_cast<Layer*>(parent); // cheaper than dynamic_cast
344         mLayerList         = parentLayer->mLayerList;
345       }
346     }
347   }
348
349   DALI_ASSERT_DEBUG(NULL != mLayerList);
350   mLayerList->RegisterLayer(*this);
351 }
352
353 void Layer::OnSceneDisconnectionInternal()
354 {
355   mLayerList->UnregisterLayer(*this);
356
357   // mLayerList is only valid when on-stage
358   mLayerList = nullptr;
359 }
360
361 const SceneGraph::Layer& Layer::GetSceneGraphLayer() const
362 {
363   return static_cast<const SceneGraph::Layer&>(GetNode()); // we know our node is a layer node
364 }
365
366 void Layer::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
367 {
368   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
369   {
370     Actor::SetDefaultProperty(index, propertyValue);
371   }
372   else
373   {
374     switch(index)
375     {
376       case Dali::Layer::Property::CLIPPING_ENABLE:
377       {
378         SetClipping(propertyValue.Get<bool>());
379         break;
380       }
381       case Dali::Layer::Property::CLIPPING_BOX:
382       {
383         Rect<int32_t> clippingBox(propertyValue.Get<Rect<int32_t> >());
384         SetClippingBox(clippingBox.x, clippingBox.y, clippingBox.width, clippingBox.height);
385         break;
386       }
387       case Dali::Layer::Property::BEHAVIOR:
388       {
389         Behavior behavior = mBehavior;
390
391         Property::Type type = propertyValue.GetType();
392         if(type == Property::STRING)
393         {
394           if(Scripting::GetEnumeration<Behavior>(propertyValue.Get<std::string>().c_str(), BEHAVIOR_TABLE, BEHAVIOR_TABLE_COUNT, behavior))
395           {
396             SetBehavior(behavior);
397           }
398         }
399         else if(type == Property::INTEGER)
400         {
401           SetBehavior(propertyValue.Get<Dali::Layer::Behavior>());
402         }
403         break;
404       }
405       case Dali::Layer::Property::DEPTH_TEST:
406       {
407         SetDepthTestDisabled(!propertyValue.Get<bool>());
408         break;
409       }
410       case Dali::Layer::Property::CONSUMES_TOUCH:
411       {
412         SetTouchConsumed(propertyValue.Get<bool>());
413         break;
414       }
415       case Dali::Layer::Property::CONSUMES_HOVER:
416       {
417         SetHoverConsumed(propertyValue.Get<bool>());
418         break;
419       }
420       default:
421       {
422         DALI_LOG_WARNING("Unknown property (%d)\n", index);
423         break;
424       }
425     } // switch(index)
426
427   } // else
428 }
429
430 Property::Value Layer::GetDefaultProperty(Property::Index index) const
431 {
432   Property::Value ret;
433   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
434   {
435     ret = Actor::GetDefaultProperty(index);
436   }
437   else
438   {
439     switch(index)
440     {
441       case Dali::Layer::Property::CLIPPING_ENABLE:
442       {
443         ret = mIsClipping;
444         break;
445       }
446       case Dali::Layer::Property::CLIPPING_BOX:
447       {
448         ret = mClippingBox;
449         break;
450       }
451       case Dali::Layer::Property::BEHAVIOR:
452       {
453         ret = mBehavior;
454         break;
455       }
456       case Dali::Layer::Property::DEPTH:
457       {
458         ret = static_cast<int>(GetDepth());
459         break;
460       }
461       case Dali::Layer::Property::DEPTH_TEST:
462       {
463         ret = !mDepthTestDisabled;
464         break;
465       }
466       case Dali::Layer::Property::CONSUMES_TOUCH:
467       {
468         ret = mTouchConsumed;
469         break;
470       }
471       case Dali::Layer::Property::CONSUMES_HOVER:
472       {
473         ret = mHoverConsumed;
474         break;
475       }
476       default:
477       {
478         DALI_LOG_WARNING("Unknown property (%d)\n", index);
479         break;
480       }
481     } // switch(index)
482   }
483
484   return ret;
485 }
486
487 Property::Value Layer::GetDefaultPropertyCurrentValue(Property::Index index) const
488 {
489   Property::Value ret;
490   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
491   {
492     ret = Actor::GetDefaultPropertyCurrentValue(index);
493   }
494   else
495   {
496     ret = GetDefaultProperty(index); // Layer only has event-side properties
497   }
498
499   return ret;
500 }
501
502 bool Layer::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/)
503 {
504   bool   done  = false;
505   Layer* layer = dynamic_cast<Layer*>(object);
506
507   if(layer)
508   {
509     std::string_view name(actionName);
510
511     if(name == ACTION_RAISE)
512     {
513       layer->Raise();
514       done = true;
515     }
516     else if(name == ACTION_LOWER)
517     {
518       layer->Lower();
519       done = true;
520     }
521     else if(name == ACTION_RAISE_TO_TOP)
522     {
523       layer->RaiseToTop();
524       done = true;
525     }
526     else if(name == ACTION_LOWER_TO_BOTTOM)
527     {
528       layer->LowerToBottom();
529       done = true;
530     }
531   }
532
533   return done;
534 }
535
536 } // namespace Internal
537
538 } // namespace Dali