Even if the layer is set to SetTouchConsumed(true), the parent must be able to handle...
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / layer-impl.cpp
1 /*
2  * Copyright (c) 2022 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   if(mBehavior != behavior)
243   {
244     mBehavior = behavior;
245
246     if(mIsOnScene)
247     {
248       // If current layer is on scene, and it's behavior changed,
249       // Change the mLayer3DParentsCount value recursively.
250       mParentImpl.RecursiveChangeLayer3dCount(mBehavior == Dali::Layer::LAYER_3D ? 1 : -1);
251     }
252
253     // Notify update side object.
254     SetBehaviorMessage(GetEventThreadServices(), GetSceneGraphLayer(), behavior);
255     // By default, disable depth test for LAYER_UI, and enable for LAYER_3D.
256     SetDepthTestDisabled(mBehavior == Dali::Layer::LAYER_UI);
257   }
258 }
259
260 void Layer::SetClipping(bool enabled)
261 {
262   if(enabled != mIsClipping)
263   {
264     mIsClipping = enabled;
265
266     // layerNode is being used in a separate thread; queue a message to set the value
267     SetClippingMessage(GetEventThreadServices(), GetSceneGraphLayer(), mIsClipping);
268   }
269 }
270
271 void Layer::SetClippingBox(int x, int y, int width, int height)
272 {
273   if((x != mClippingBox.x) ||
274      (y != mClippingBox.y) ||
275      (width != mClippingBox.width) ||
276      (height != mClippingBox.height))
277   {
278     // Clipping box is not animatable; this is the most up-to-date value
279     mClippingBox.Set(x, y, width, height);
280
281     // Convert mClippingBox to GL based coordinates (from bottom-left)
282     ClippingBox clippingBox(mClippingBox);
283
284     if(mScene)
285     {
286       clippingBox.y = static_cast<int32_t>(mScene->GetSize().height) - clippingBox.y - clippingBox.height;
287
288       // layerNode is being used in a separate thread; queue a message to set the value
289       SetClippingBoxMessage(GetEventThreadServices(), GetSceneGraphLayer(), clippingBox);
290     }
291   }
292 }
293
294 void Layer::SetDepthTestDisabled(bool disable)
295 {
296   if(disable != mDepthTestDisabled)
297   {
298     mDepthTestDisabled = disable;
299
300     // Send message.
301     // layerNode is being used in a separate thread; queue a message to set the value
302     SetDepthTestDisabledMessage(GetEventThreadServices(), GetSceneGraphLayer(), mDepthTestDisabled);
303   }
304 }
305
306 bool Layer::IsDepthTestDisabled() const
307 {
308   return mDepthTestDisabled;
309 }
310
311 void Layer::SetSortFunction(Dali::Layer::SortFunctionType function)
312 {
313   if(function != mSortFunction)
314   {
315     mSortFunction = function;
316
317     // layerNode is being used in a separate thread; queue a message to set the value
318     SetSortFunctionMessage(GetEventThreadServices(), GetSceneGraphLayer(), mSortFunction);
319   }
320 }
321
322 void Layer::SetTouchConsumed(bool consume)
323 {
324   if(mTouchConsumed != consume)
325   {
326     if(consume)
327     {
328       this->TouchedSignal().Connect(this, &Layer::OnTouched);
329     }
330     else
331     {
332       this->TouchedSignal().Disconnect(this, &Layer::OnTouched);
333     }
334   }
335   mTouchConsumed = consume;
336 }
337
338 bool Layer::OnTouched(Dali::Actor actor, const TouchEvent& touch)
339 {
340   // This event is only called when mTouchConsumed is true. So touch always consumed.
341   return true;
342 }
343
344 bool Layer::IsTouchConsumed() const
345 {
346   return mTouchConsumed;
347 }
348
349 void Layer::SetHoverConsumed(bool consume)
350 {
351   mHoverConsumed = consume;
352 }
353
354 bool Layer::IsHoverConsumed() const
355 {
356   return mHoverConsumed;
357 }
358
359 void Layer::OnSceneConnectionInternal()
360 {
361   if(!mIsRoot)
362   {
363     DALI_ASSERT_DEBUG(NULL == mLayerList);
364
365     // Find the ordered layer-list
366     for(Actor* parent = GetParent(); parent != nullptr; parent = parent->GetParent())
367     {
368       if(parent->IsLayer())
369       {
370         Layer* parentLayer = static_cast<Layer*>(parent); // cheaper than dynamic_cast
371         mLayerList         = parentLayer->mLayerList;
372       }
373     }
374   }
375
376   DALI_ASSERT_DEBUG(NULL != mLayerList);
377   mLayerList->RegisterLayer(*this);
378 }
379
380 void Layer::OnSceneDisconnectionInternal()
381 {
382   mLayerList->UnregisterLayer(*this);
383
384   // mLayerList is only valid when on-stage
385   mLayerList = nullptr;
386 }
387
388 const SceneGraph::Layer& Layer::GetSceneGraphLayer() const
389 {
390   return static_cast<const SceneGraph::Layer&>(GetNode()); // we know our node is a layer node
391 }
392
393 void Layer::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
394 {
395   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
396   {
397     Actor::SetDefaultProperty(index, propertyValue);
398   }
399   else
400   {
401     switch(index)
402     {
403       case Dali::Layer::Property::CLIPPING_ENABLE:
404       {
405         SetClipping(propertyValue.Get<bool>());
406         break;
407       }
408       case Dali::Layer::Property::CLIPPING_BOX:
409       {
410         Rect<int32_t> clippingBox(propertyValue.Get<Rect<int32_t> >());
411         SetClippingBox(clippingBox.x, clippingBox.y, clippingBox.width, clippingBox.height);
412         break;
413       }
414       case Dali::Layer::Property::BEHAVIOR:
415       {
416         Behavior behavior = mBehavior;
417
418         Property::Type type = propertyValue.GetType();
419         if(type == Property::STRING)
420         {
421           if(Scripting::GetEnumeration<Behavior>(propertyValue.Get<std::string>().c_str(), BEHAVIOR_TABLE, BEHAVIOR_TABLE_COUNT, behavior))
422           {
423             SetBehavior(behavior);
424           }
425         }
426         else if(type == Property::INTEGER)
427         {
428           SetBehavior(propertyValue.Get<Dali::Layer::Behavior>());
429         }
430         break;
431       }
432       case Dali::Layer::Property::DEPTH_TEST:
433       {
434         SetDepthTestDisabled(!propertyValue.Get<bool>());
435         break;
436       }
437       case Dali::Layer::Property::CONSUMES_TOUCH:
438       {
439         SetTouchConsumed(propertyValue.Get<bool>());
440         break;
441       }
442       case Dali::Layer::Property::CONSUMES_HOVER:
443       {
444         SetHoverConsumed(propertyValue.Get<bool>());
445         break;
446       }
447       default:
448       {
449         DALI_LOG_WARNING("Unknown property (%d)\n", index);
450         break;
451       }
452     } // switch(index)
453
454   } // else
455 }
456
457 Property::Value Layer::GetDefaultProperty(Property::Index index) const
458 {
459   Property::Value ret;
460   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
461   {
462     ret = Actor::GetDefaultProperty(index);
463   }
464   else
465   {
466     switch(index)
467     {
468       case Dali::Layer::Property::CLIPPING_ENABLE:
469       {
470         ret = mIsClipping;
471         break;
472       }
473       case Dali::Layer::Property::CLIPPING_BOX:
474       {
475         ret = mClippingBox;
476         break;
477       }
478       case Dali::Layer::Property::BEHAVIOR:
479       {
480         ret = mBehavior;
481         break;
482       }
483       case Dali::Layer::Property::DEPTH:
484       {
485         ret = static_cast<int>(GetDepth());
486         break;
487       }
488       case Dali::Layer::Property::DEPTH_TEST:
489       {
490         ret = !mDepthTestDisabled;
491         break;
492       }
493       case Dali::Layer::Property::CONSUMES_TOUCH:
494       {
495         ret = mTouchConsumed;
496         break;
497       }
498       case Dali::Layer::Property::CONSUMES_HOVER:
499       {
500         ret = mHoverConsumed;
501         break;
502       }
503       default:
504       {
505         DALI_LOG_WARNING("Unknown property (%d)\n", index);
506         break;
507       }
508     } // switch(index)
509   }
510
511   return ret;
512 }
513
514 Property::Value Layer::GetDefaultPropertyCurrentValue(Property::Index index) const
515 {
516   Property::Value ret;
517   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
518   {
519     ret = Actor::GetDefaultPropertyCurrentValue(index);
520   }
521   else
522   {
523     ret = GetDefaultProperty(index); // Layer only has event-side properties
524   }
525
526   return ret;
527 }
528
529 bool Layer::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/)
530 {
531   bool   done  = false;
532   Layer* layer = dynamic_cast<Layer*>(object);
533
534   if(layer)
535   {
536     std::string_view name(actionName);
537
538     if(name == ACTION_RAISE)
539     {
540       layer->Raise();
541       done = true;
542     }
543     else if(name == ACTION_LOWER)
544     {
545       layer->Lower();
546       done = true;
547     }
548     else if(name == ACTION_RAISE_TO_TOP)
549     {
550       layer->RaiseToTop();
551       done = true;
552     }
553     else if(name == ACTION_LOWER_TO_BOTTOM)
554     {
555       layer->LowerToBottom();
556       done = true;
557     }
558   }
559
560   return done;
561 }
562
563 } // namespace Internal
564
565 } // namespace Dali