41ddf8f60ef1de79d3adfa96f5a33674471a0b3a
[platform/core/uifw/dali-adaptor.git] / dali / integration-api / adaptor-framework / scene-holder-impl.cpp
1 /*
2  * Copyright (c) 2020 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/integration-api/adaptor-framework/scene-holder-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <sys/time.h>
23 #include <dali/public-api/actors/actor.h>
24 #include <dali/public-api/actors/layer.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/events/key-event-integ.h>
27 #include <dali/integration-api/events/touch-event-integ.h>
28 #include <dali/integration-api/events/hover-event-integ.h>
29 #include <dali/integration-api/events/wheel-event-integ.h>
30
31 // INTERNAL INCLUDES
32 #include <dali/internal/adaptor/common/adaptor-impl.h>
33 #include <dali/internal/adaptor/common/lifecycle-observer.h>
34 #include <dali/internal/input/common/key-impl.h>
35 #include <dali/internal/input/common/physical-keyboard-impl.h>
36
37 namespace Dali
38 {
39
40 namespace Internal
41 {
42
43 namespace Adaptor
44 {
45
46 namespace
47 {
48
49 #if defined(DEBUG_ENABLED)
50 Integration::Log::Filter* gTouchEventLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH");
51 #endif
52
53 // Copied from x server
54 static uint32_t GetCurrentMilliSeconds(void)
55 {
56   struct timeval tv;
57
58   struct timespec tp;
59   static clockid_t clockid;
60
61   if (!clockid)
62   {
63 #ifdef CLOCK_MONOTONIC_COARSE
64     if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
65       (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
66     {
67       clockid = CLOCK_MONOTONIC_COARSE;
68     }
69     else
70 #endif
71     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
72     {
73       clockid = CLOCK_MONOTONIC;
74     }
75     else
76     {
77       clockid = ~0L;
78     }
79   }
80   if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
81   {
82     return static_cast<uint32_t>( (tp.tv_sec * 1000 ) + (tp.tv_nsec / 1000000L) );
83   }
84
85   gettimeofday(&tv, NULL);
86   return static_cast<uint32_t>( (tv.tv_sec * 1000 ) + (tv.tv_usec / 1000) );
87 }
88
89 } // unnamed namespace
90
91 uint32_t SceneHolder::mSceneHolderCounter = 0;
92
93 class SceneHolder::SceneHolderLifeCycleObserver : public LifeCycleObserver
94 {
95 public:
96
97   SceneHolderLifeCycleObserver(Adaptor*& adaptor)
98   : mAdaptor( adaptor )
99   {
100   };
101
102 private: // Adaptor::LifeCycleObserver interface
103
104   void OnStart() override {};
105   void OnPause() override {};
106   void OnResume() override {};
107   void OnStop() override {};
108   void OnDestroy() override
109   {
110     mAdaptor = nullptr;
111   };
112
113 private:
114   Adaptor*& mAdaptor;
115 };
116
117
118 SceneHolder::SceneHolder()
119 : mLifeCycleObserver( new SceneHolderLifeCycleObserver( mAdaptor ) ),
120   mId( mSceneHolderCounter++ ),
121   mSurface( nullptr ),
122   mAdaptor( nullptr ),
123   mIsBeingDeleted( false ),
124   mAdaptorStarted( false ),
125   mVisible( true )
126 {
127 }
128
129 SceneHolder::~SceneHolder()
130 {
131   if ( mAdaptor )
132   {
133     mAdaptor->RemoveObserver( *mLifeCycleObserver.get() );
134     mAdaptor->RemoveWindow( this );
135
136     mAdaptor->DeleteSurface( *mSurface.get() );
137
138     mAdaptor = nullptr;
139   }
140
141   if ( mScene )
142   {
143     mScene.Discard();
144   }
145 }
146
147 void SceneHolder::Add( Dali::Actor actor )
148 {
149   if ( mScene )
150   {
151     mScene.Add( actor );
152   }
153 }
154
155 void SceneHolder::Remove( Dali::Actor actor )
156 {
157   if ( mScene )
158   {
159     mScene.Remove( actor );
160   }
161 }
162
163 Dali::Layer SceneHolder::GetRootLayer() const
164 {
165   return mScene ? mScene.GetRootLayer() : Dali::Layer();
166 }
167
168 uint32_t SceneHolder::GetId() const
169 {
170   return mId;
171 }
172
173 std::string SceneHolder::GetName() const
174 {
175   return mName;
176 }
177
178 bool SceneHolder::IsVisible() const
179 {
180   return mVisible;
181 }
182
183 Dali::Integration::Scene SceneHolder::GetScene()
184 {
185   return mScene;
186 }
187
188 void SceneHolder::SetSurface(Dali::RenderSurfaceInterface* surface)
189 {
190   mSurface.reset( surface );
191
192   mScene.SurfaceReplaced();
193
194   SurfaceResized( false );
195
196   unsigned int dpiHorizontal, dpiVertical;
197   dpiHorizontal = dpiVertical = 0;
198
199   mSurface->GetDpi( dpiHorizontal, dpiVertical );
200   mScene.SetDpi( Vector2( static_cast<float>( dpiHorizontal ), static_cast<float>( dpiVertical ) ) );
201
202   mSurface->SetAdaptor( *mAdaptor );
203
204   OnSurfaceSet( surface );
205 }
206
207 void SceneHolder::SurfaceResized( bool forceUpdate )
208 {
209   PositionSize surfacePositionSize = mSurface->GetPositionSize();
210   int orientation = mSurface->GetOrientation();
211   mScene.SurfaceResized( static_cast<float>( surfacePositionSize.width ), static_cast<float>( surfacePositionSize.height ), orientation, forceUpdate );
212 }
213
214 Dali::RenderSurfaceInterface* SceneHolder::GetSurface() const
215 {
216   return mSurface.get();
217 }
218
219 void SceneHolder::SetBackgroundColor( const Vector4& color )
220 {
221   if( mScene )
222   {
223     mScene.SetBackgroundColor( color );
224   }
225 }
226
227 Vector4 SceneHolder::GetBackgroundColor() const
228 {
229   return mScene ? mScene.GetBackgroundColor() : Color::BLACK;
230 }
231
232 void SceneHolder::SetAdaptor(Dali::Adaptor& adaptor)
233 {
234   // Avoid doing this more than once
235   if( mAdaptorStarted )
236   {
237     return;
238   }
239
240   mAdaptorStarted = true;
241
242   // Create the scene
243   PositionSize surfacePositionSize = mSurface->GetPositionSize();
244   mScene = Dali::Integration::Scene::New( Size(static_cast<float>( surfacePositionSize.width ), static_cast<float>( surfacePositionSize.height )) );
245
246   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation( adaptor );
247   mAdaptor = &adaptorImpl;
248
249   // Create an observer for the adaptor lifecycle
250   mAdaptor->AddObserver( *mLifeCycleObserver );
251
252   if ( mSurface )
253   {
254     unsigned int dpiHorizontal, dpiVertical;
255     dpiHorizontal = dpiVertical = 0;
256
257     mSurface->GetDpi( dpiHorizontal, dpiVertical );
258     mScene.SetDpi( Vector2( static_cast<float>( dpiHorizontal ), static_cast<float>( dpiVertical ) ) );
259
260     mSurface->SetAdaptor( *mAdaptor );
261   }
262
263   OnAdaptorSet( adaptor );
264 }
265
266 void SceneHolder::Pause()
267 {
268   Reset();
269
270   OnPause();
271 }
272
273 void SceneHolder::Resume()
274 {
275   Reset();
276
277   OnResume();
278 }
279
280 void SceneHolder::FeedTouchPoint( Dali::Integration::Point& point, int timeStamp )
281 {
282   if( timeStamp < 1 )
283   {
284     timeStamp = GetCurrentMilliSeconds();
285   }
286
287   RecalculateTouchPosition( point );
288
289   Integration::TouchEvent touchEvent;
290   Integration::HoverEvent hoverEvent;
291   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
292   if( type != Integration::TouchEventCombiner::DispatchNone )
293   {
294     DALI_LOG_INFO( gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y );
295
296     // Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback.
297     // Keep the handle alive until the core events are processed.
298     Dali::BaseHandle sceneHolder( this );
299
300     // First the touch and/or hover event & related gesture events are queued
301     if( type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth )
302     {
303       mScene.QueueEvent( touchEvent );
304     }
305
306     if( type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth )
307     {
308       mScene.QueueEvent( hoverEvent );
309     }
310
311     // Next the events are processed with a single call into Core
312     mAdaptor->ProcessCoreEvents();
313   }
314 }
315
316 void SceneHolder::FeedWheelEvent( Dali::Integration::WheelEvent& wheelEvent )
317 {
318   // Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback.
319   // Keep the handle alive until the core events are processed.
320   Dali::BaseHandle sceneHolder( this );
321
322   mScene.QueueEvent( wheelEvent );
323   mAdaptor->ProcessCoreEvents();
324 }
325
326 void SceneHolder::FeedKeyEvent( Dali::Integration::KeyEvent& keyEvent )
327 {
328   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
329   if( physicalKeyboard )
330   {
331     if( ! KeyLookup::IsDeviceButton( keyEvent.keyName.c_str() ) )
332     {
333       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
334     }
335   }
336
337   // Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback.
338   // Keep the handle alive until the core events are processed.
339   Dali::BaseHandle sceneHolder( this );
340
341   // Create send KeyEvent to Core.
342   mScene.QueueEvent( keyEvent );
343   mAdaptor->ProcessCoreEvents();
344 }
345
346 Dali::Integration::SceneHolder SceneHolder::Get( Dali::Actor actor )
347 {
348   SceneHolder* sceneHolderImpl = nullptr;
349
350   if ( Internal::Adaptor::Adaptor::IsAvailable() )
351   {
352     Dali::Internal::Adaptor::Adaptor& adaptor = Internal::Adaptor::Adaptor::GetImplementation( Internal::Adaptor::Adaptor::Get() );
353     sceneHolderImpl = adaptor.GetWindow( actor );
354   }
355
356   return Dali::Integration::SceneHolder( sceneHolderImpl );
357 }
358
359 void SceneHolder::Reset()
360 {
361   mCombiner.Reset();
362
363   // Any touch listeners should be told of the interruption.
364   Integration::TouchEvent event;
365   Integration::Point point;
366   point.SetState( PointState::INTERRUPTED );
367   event.AddPoint( point );
368
369   // First the touch event & related gesture events are queued
370   mScene.QueueEvent( event );
371
372   // Next the events are processed with a single call into Core
373   mAdaptor->ProcessCoreEvents();
374 }
375
376
377 }// Adaptor
378
379 }// Internal
380
381 } // Dali