7162a1c715d5b2317faf0c715e602307730ef13f
[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();
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()
208 {
209   PositionSize surfacePositionSize = mSurface->GetPositionSize();
210   mScene.SurfaceResized( static_cast<float>( surfacePositionSize.width ), static_cast<float>( surfacePositionSize.height ) );
211 }
212
213 Dali::RenderSurfaceInterface* SceneHolder::GetSurface() const
214 {
215   return mSurface.get();
216 }
217
218 void SceneHolder::SetBackgroundColor( const Vector4& color )
219 {
220   if( mScene )
221   {
222     mScene.SetBackgroundColor( color );
223   }
224 }
225
226 Vector4 SceneHolder::GetBackgroundColor() const
227 {
228   return mScene ? mScene.GetBackgroundColor() : Color::BLACK;
229 }
230
231 void SceneHolder::SetAdaptor(Dali::Adaptor& adaptor)
232 {
233   // Avoid doing this more than once
234   if( mAdaptorStarted )
235   {
236     return;
237   }
238
239   mAdaptorStarted = true;
240
241   // Create the scene
242   PositionSize surfacePositionSize = mSurface->GetPositionSize();
243   mScene = Dali::Integration::Scene::New( Size(static_cast<float>( surfacePositionSize.width ), static_cast<float>( surfacePositionSize.height )) );
244
245   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation( adaptor );
246   mAdaptor = &adaptorImpl;
247
248   // Create an observer for the adaptor lifecycle
249   mAdaptor->AddObserver( *mLifeCycleObserver );
250
251   if ( mSurface )
252   {
253     unsigned int dpiHorizontal, dpiVertical;
254     dpiHorizontal = dpiVertical = 0;
255
256     mSurface->GetDpi( dpiHorizontal, dpiVertical );
257     mScene.SetDpi( Vector2( static_cast<float>( dpiHorizontal ), static_cast<float>( dpiVertical ) ) );
258
259     mSurface->SetAdaptor( *mAdaptor );
260   }
261
262   OnAdaptorSet( adaptor );
263 }
264
265 void SceneHolder::Pause()
266 {
267   Reset();
268
269   OnPause();
270 }
271
272 void SceneHolder::Resume()
273 {
274   Reset();
275
276   OnResume();
277 }
278
279 void SceneHolder::FeedTouchPoint( Dali::Integration::Point& point, int timeStamp )
280 {
281   if( timeStamp < 1 )
282   {
283     timeStamp = GetCurrentMilliSeconds();
284   }
285
286   RecalculateTouchPosition( point );
287
288   Integration::TouchEvent touchEvent;
289   Integration::HoverEvent hoverEvent;
290   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
291   if( type != Integration::TouchEventCombiner::DispatchNone )
292   {
293     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 );
294
295     // Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback.
296     // Keep the handle alive until the core events are processed.
297     Dali::BaseHandle sceneHolder( this );
298
299     // First the touch and/or hover event & related gesture events are queued
300     if( type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth )
301     {
302       mScene.QueueEvent( touchEvent );
303     }
304
305     if( type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth )
306     {
307       mScene.QueueEvent( hoverEvent );
308     }
309
310     // Next the events are processed with a single call into Core
311     mAdaptor->ProcessCoreEvents();
312   }
313 }
314
315 void SceneHolder::FeedWheelEvent( Dali::Integration::WheelEvent& wheelEvent )
316 {
317   // Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback.
318   // Keep the handle alive until the core events are processed.
319   Dali::BaseHandle sceneHolder( this );
320
321   mScene.QueueEvent( wheelEvent );
322   mAdaptor->ProcessCoreEvents();
323 }
324
325 void SceneHolder::FeedKeyEvent( Dali::Integration::KeyEvent& keyEvent )
326 {
327   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
328   if( physicalKeyboard )
329   {
330     if( ! KeyLookup::IsDeviceButton( keyEvent.keyName.c_str() ) )
331     {
332       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
333     }
334   }
335
336   // Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback.
337   // Keep the handle alive until the core events are processed.
338   Dali::BaseHandle sceneHolder( this );
339
340   // Create send KeyEvent to Core.
341   mScene.QueueEvent( keyEvent );
342   mAdaptor->ProcessCoreEvents();
343 }
344
345 Dali::Integration::SceneHolder SceneHolder::Get( Dali::Actor actor )
346 {
347   SceneHolder* sceneHolderImpl = nullptr;
348
349   if ( Internal::Adaptor::Adaptor::IsAvailable() )
350   {
351     Dali::Internal::Adaptor::Adaptor& adaptor = Internal::Adaptor::Adaptor::GetImplementation( Internal::Adaptor::Adaptor::Get() );
352     sceneHolderImpl = adaptor.GetWindow( actor );
353   }
354
355   return Dali::Integration::SceneHolder( sceneHolderImpl );
356 }
357
358 void SceneHolder::Reset()
359 {
360   mCombiner.Reset();
361
362   // Any touch listeners should be told of the interruption.
363   Integration::TouchEvent event;
364   Integration::Point point;
365   point.SetState( PointState::INTERRUPTED );
366   event.AddPoint( point );
367
368   // First the touch event & related gesture events are queued
369   mScene.QueueEvent( event );
370
371   // Next the events are processed with a single call into Core
372   mAdaptor->ProcessCoreEvents();
373 }
374
375
376 }// Adaptor
377
378 }// Internal
379
380 } // Dali