5a65a8ebc730579ae22e41a941ffe3dc381d00cc
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / adaptor-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/internal/adaptor/common/adaptor-impl.h>
20 #include <dali/internal/addons/common/addon-manager-impl.h>
21 #include <dali/internal/addons/common/addon-manager-factory.h>
22 #include <dali/internal/adaptor/common/adaptor-builder-impl.h>
23
24 // EXTERNAL INCLUDES
25 #include <errno.h>
26 #include <sys/stat.h>
27 #include <dali/public-api/actors/layer.h>
28 #include <dali/public-api/object/any.h>
29 #include <dali/public-api/object/object-registry.h>
30 #include <dali/public-api/events/wheel-event.h>
31 #include <dali/devel-api/actors/actor-devel.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/integration-api/core.h>
34 #include <dali/integration-api/context-notifier.h>
35 #include <dali/integration-api/profiling.h>
36 #include <dali/integration-api/input-options.h>
37 #include <dali/integration-api/events/key-event-integ.h>
38 #include <dali/integration-api/events/touch-event-integ.h>
39 #include <dali/integration-api/events/wheel-event-integ.h>
40 #include <dali/integration-api/processor-interface.h>
41 #include <dali/integration-api/addon-manager.h>
42
43 // INTERNAL INCLUDES
44 #include <dali/public-api/dali-adaptor-common.h>
45 #include <dali/internal/system/common/thread-controller.h>
46 #include <dali/internal/system/common/performance-interface-factory.h>
47 #include <dali/internal/adaptor/common/lifecycle-observer.h>
48 #include <dali/internal/adaptor/common/thread-controller-interface.h>
49
50 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
51 #include <dali/internal/graphics/gles/egl-graphics.h> // Temporary until Core is abstracted
52
53 #include <dali/devel-api/text-abstraction/font-client.h>
54
55 #include <dali/internal/system/common/callback-manager.h>
56 #include <dali/internal/accessibility/common/tts-player-impl.h>
57 #include <dali/internal/accessibility/common/accessibility-adaptor-impl.h>
58 #include <dali/internal/window-system/common/event-handler.h>
59 #include <dali/internal/graphics/gles/gl-proxy-implementation.h>
60 #include <dali/internal/graphics/gles/gl-implementation.h>
61 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
62 #include <dali/internal/graphics/common/egl-image-extensions.h>
63 #include <dali/internal/clipboard/common/clipboard-impl.h>
64 #include <dali/internal/system/common/object-profiler.h>
65 #include <dali/internal/window-system/common/display-connection.h>
66 #include <dali/internal/window-system/common/display-utils.h> // For Utils::MakeUnique
67 #include <dali/internal/window-system/common/window-impl.h>
68 #include <dali/internal/window-system/common/window-render-surface.h>
69
70 #include <dali/internal/system/common/logging.h>
71
72 #include <dali/internal/system/common/locale-utils.h>
73 #include <dali/internal/imaging/common/image-loader-plugin-proxy.h>
74 #include <dali/internal/imaging/common/image-loader.h>
75
76 #include <dali/internal/system/common/configuration-manager.h>
77 #include <dali/internal/system/common/environment-variables.h>
78
79 using Dali::TextAbstraction::FontClient;
80
81 extern std::string GetSystemCachePath();
82
83 namespace Dali
84 {
85
86 namespace Internal
87 {
88
89 namespace Adaptor
90 {
91
92 namespace
93 {
94
95 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
96
97 } // unnamed namespace
98
99 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
100 {
101   Dali::Adaptor* adaptor = new Dali::Adaptor;
102   Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions );
103   adaptor->mImpl = impl;
104
105   Dali::Internal::Adaptor::AdaptorBuilder* mAdaptorBuilder = new AdaptorBuilder();
106   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
107
108   impl->Initialize( graphicsFactory, configuration );
109   delete mAdaptorBuilder; // Not needed anymore as the graphics interface has now been created
110
111   return adaptor;
112 }
113
114 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
115 {
116   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
117   Dali::Adaptor* adaptor = New( window, windowImpl.GetSurface(), configuration, environmentOptions );
118   windowImpl.SetAdaptor( *adaptor );
119   return adaptor;
120 }
121
122 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
123 {
124   Dali::Adaptor* adaptor = new Dali::Adaptor; // Public adaptor
125   Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions ); // Impl adaptor
126   adaptor->mImpl = impl;
127
128   impl->Initialize( graphicsFactory, configuration );
129
130   return adaptor;
131 } // Called second
132
133 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
134 {
135   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
136   Dali::Adaptor* adaptor = New( graphicsFactory, window, windowImpl.GetSurface(), configuration, environmentOptions );
137   windowImpl.SetAdaptor( *adaptor );
138   return adaptor;
139 } // Called first
140
141 void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration::ContextLoss configuration )
142 {
143   // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
144   Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
145   mEnvironmentOptions->SetLogFunction( logFunction );
146   mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
147
148   mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
149
150   std::string path;
151   GetDataStoragePath( path );
152   mPlatformAbstraction->SetDataStoragePath( path );
153
154   if( mEnvironmentOptions->PerformanceServerRequired() )
155   {
156     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
157   }
158
159   mEnvironmentOptions->CreateTraceManager( mPerformanceInterface );
160   mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
161
162   mCallbackManager = CallbackManager::New();
163
164   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
165
166   DALI_ASSERT_DEBUG( defaultWindow->GetSurface() && "Surface not initialized" );
167
168   mGraphics = std::unique_ptr< GraphicsInterface >( &graphicsFactory.Create() );
169   mGraphics->Initialize( mEnvironmentOptions );
170
171   GraphicsInterface* graphics = mGraphics.get(); // This interface is temporary until Core has been updated to match
172   auto eglGraphics = static_cast<EglGraphics *>( graphics );
173
174   // This will only be created once
175   eglGraphics->Create();
176
177   GlImplementation& mGLES = eglGraphics->GetGlesInterface();
178   EglSyncImplementation& eglSyncImpl = eglGraphics->GetSyncImplementation();
179   EglContextHelperImplementation& eglContextHelperImpl = eglGraphics->GetContextHelperImplementation();
180
181   // Create the AddOnManager
182   mAddOnManager.reset( Dali::Internal::AddOnManagerFactory::CreateAddOnManager() );
183
184   mCore = Integration::Core::New( *this,
185                                   *mPlatformAbstraction,
186                                   mGLES,
187                                   eglSyncImpl,
188                                   eglContextHelperImpl,
189                                   ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
190                                   mGraphics->GetDepthBufferRequired(),
191                                   mGraphics->GetStencilBufferRequired(),
192                                   mGraphics->GetPartialUpdateRequired() );
193
194
195   defaultWindow->SetAdaptor( Get() );
196
197   Dali::Integration::SceneHolder defaultSceneHolder( defaultWindow );
198
199   mWindowCreatedSignal.Emit( defaultSceneHolder );
200
201   const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
202   if( 0u < timeInterval )
203   {
204     mObjectProfiler = new ObjectProfiler( mCore->GetObjectRegistry(), timeInterval );
205   }
206
207   mNotificationTrigger = TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
208
209   mDisplayConnection = Dali::DisplayConnection::New( *mGraphics, defaultWindow->GetSurface()->GetSurfaceType() );
210
211   mThreadController = new ThreadController( *this, *mEnvironmentOptions, mThreadMode );
212
213   // Should be called after Core creation
214   if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
215   {
216     Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
217   }
218   if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
219   {
220     Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
221   }
222   if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
223   {
224     Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
225   }
226   if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
227   {
228     Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
229   }
230   if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
231   {
232     Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
233   }
234   if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
235   {
236     Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
237   }
238   if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
239   {
240     Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
241   }
242   if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
243   {
244     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
245   }
246   if( mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0 )
247   {
248     Integration::SetPanGestureUseActualTimes( mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false );
249   }
250   if( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0 )
251   {
252     Integration::SetPanGestureInterpolationTimeRange( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() );
253   }
254   if( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0 )
255   {
256     Integration::SetPanGestureScalarOnlyPredictionEnabled( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false  );
257   }
258   if( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0 )
259   {
260     Integration::SetPanGestureTwoPointPredictionEnabled( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false  );
261   }
262   if( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0 )
263   {
264     Integration::SetPanGestureTwoPointInterpolatePastTime( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() );
265   }
266   if( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f )
267   {
268     Integration::SetPanGestureTwoPointVelocityBias( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() );
269   }
270   if( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f )
271   {
272     Integration::SetPanGestureTwoPointAccelerationBias( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() );
273   }
274   if( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0 )
275   {
276     Integration::SetPanGestureMultitapSmoothingRange( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() );
277   }
278   if( mEnvironmentOptions->GetMinimumPanDistance() >= 0 )
279   {
280     Integration::SetPanGestureMinimumDistance( mEnvironmentOptions->GetMinimumPanDistance() );
281   }
282   if( mEnvironmentOptions->GetMinimumPanEvents() >= 0 )
283   {
284     Integration::SetPanGestureMinimumPanEvents( mEnvironmentOptions->GetMinimumPanEvents() );
285   }
286   if( mEnvironmentOptions->GetMinimumPinchDistance() >= 0 )
287   {
288     Integration::SetPinchGestureMinimumDistance( mEnvironmentOptions->GetMinimumPinchDistance() );
289   }
290   if( mEnvironmentOptions->GetMinimumPinchTouchEvents() >= 0 )
291   {
292     Integration::SetPinchGestureMinimumTouchEvents( mEnvironmentOptions->GetMinimumPinchTouchEvents() );
293   }
294   if( mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() >= 0 )
295   {
296     Integration::SetPinchGestureMinimumTouchEventsAfterStart( mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() );
297   }
298   if( mEnvironmentOptions->GetMinimumRotationTouchEvents() >= 0 )
299   {
300     Integration::SetRotationGestureMinimumTouchEvents( mEnvironmentOptions->GetMinimumRotationTouchEvents() );
301   }
302   if( mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() >= 0 )
303   {
304     Integration::SetRotationGestureMinimumTouchEventsAfterStart( mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() );
305   }
306   if( mEnvironmentOptions->GetLongPressMinimumHoldingTime() >= 0 )
307   {
308     Integration::SetLongPressMinimumHoldingTime( mEnvironmentOptions->GetLongPressMinimumHoldingTime() );
309   }
310
311   std::string systemCachePath = GetSystemCachePath();
312   if( ! systemCachePath.empty() )
313   {
314     const int dir_err = mkdir( systemCachePath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH );
315     if ( 0 != dir_err && errno != EEXIST )
316     {
317       DALI_LOG_ERROR( "Error creating system cache directory: %s!\n", systemCachePath.c_str() );
318       exit( 1 );
319     }
320   }
321
322   mConfigurationManager = Utils::MakeUnique<ConfigurationManager>( systemCachePath, eglGraphics, mThreadController );
323 }
324
325 Adaptor::~Adaptor()
326 {
327   // Ensure stop status
328   Stop();
329
330   // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
331   gThreadLocalAdaptor = NULL;
332
333   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
334   {
335     (*iter)->OnDestroy();
336   }
337
338   // Clear out all the handles to Windows
339   mWindows.clear();
340
341   delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
342   delete mObjectProfiler;
343
344   delete mCore;
345
346   delete mDisplayConnection;
347   delete mPlatformAbstraction;
348   delete mCallbackManager;
349   delete mPerformanceInterface;
350
351   mGraphics->Destroy();
352
353   // uninstall it on this thread (main actor thread)
354   Dali::Integration::Log::UninstallLogFunction();
355
356   // Delete environment options if we own it
357   if( mEnvironmentOptionsOwned )
358   {
359     delete mEnvironmentOptions;
360   }
361 }
362
363 void Adaptor::Start()
364 {
365   // It doesn't support restart after stop at this moment to support restarting, need more testing
366   if( READY != mState )
367   {
368     return;
369   }
370
371   mCore->Initialize();
372
373   SetupSystemInformation();
374
375   // Start the callback manager
376   mCallbackManager->Start();
377
378   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
379
380   unsigned int dpiHor, dpiVer;
381   dpiHor = dpiVer = 0;
382
383   defaultWindow->GetSurface()->GetDpi( dpiHor, dpiVer );
384
385   // set the DPI value for font rendering
386   FontClient fontClient = FontClient::Get();
387   fontClient.SetDpi( dpiHor, dpiVer );
388
389   // Initialize the thread controller
390   mThreadController->Initialize();
391
392   // Set max texture size
393   if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
394   {
395     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
396   }
397   else
398   {
399     unsigned int maxTextureSize = mConfigurationManager->GetMaxTextureSize();
400     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( maxTextureSize );
401   }
402
403   ProcessCoreEvents(); // Ensure any startup messages are processed.
404
405   // Initialize the image loader plugin
406   Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
407
408   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
409   {
410     (*iter)->OnStart();
411   }
412
413   if (mAddOnManager)
414   {
415     mAddOnManager->Start();
416   }
417 }
418
419 // Dali::Internal::Adaptor::Adaptor::Pause
420 void Adaptor::Pause()
421 {
422   // Only pause the adaptor if we're actually running.
423   if( RUNNING == mState )
424   {
425     // Inform observers that we are about to be paused.
426     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
427     {
428       (*iter)->OnPause();
429     }
430
431     // Extensions
432     if (mAddOnManager)
433     {
434       mAddOnManager->Pause();
435     }
436
437     // Pause all windows event handlers when adaptor paused
438     for( auto window : mWindows )
439     {
440       window->Pause();
441     }
442
443     mThreadController->Pause();
444     mState = PAUSED;
445
446     // Ensure any messages queued during pause callbacks are processed by doing another update.
447     RequestUpdateOnce();
448
449     DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Paused\n" );
450   }
451   else
452   {
453     DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Not paused [%d]\n", mState );
454   }
455 }
456
457 // Dali::Internal::Adaptor::Adaptor::Resume
458 void Adaptor::Resume()
459 {
460   // Only resume the adaptor if we are in the suspended state.
461   if( PAUSED == mState )
462   {
463     mState = RUNNING;
464
465     // Reset the event handlers when adaptor resumed
466     for( auto window : mWindows )
467     {
468       window->Resume();
469     }
470
471     // Resume AddOnManager
472     if (mAddOnManager)
473     {
474       mAddOnManager->Resume();
475     }
476
477     // Inform observers that we have resumed.
478     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
479     {
480       (*iter)->OnResume();
481     }
482
483     // Trigger processing of events queued up while paused
484     mCore->ProcessEvents();
485
486     // Do at end to ensure our first update/render after resumption includes the processed messages as well
487     mThreadController->Resume();
488
489     DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Resumed\n");
490   }
491   else
492   {
493     DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Not resumed [%d]\n", mState );
494   }
495 }
496
497 void Adaptor::Stop()
498 {
499   if( RUNNING == mState ||
500       PAUSED  == mState ||
501       PAUSED_WHILE_HIDDEN == mState )
502   {
503     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
504     {
505       (*iter)->OnStop();
506     }
507
508     if (mAddOnManager)
509     {
510       mAddOnManager->Stop();
511     }
512
513     mThreadController->Stop();
514
515     // Delete the TTS player
516     for( int i =0; i < Dali::TtsPlayer::MODE_NUM; i++ )
517     {
518       if( mTtsPlayers[i] )
519       {
520         mTtsPlayers[i].Reset();
521       }
522     }
523
524     // Destroy the image loader plugin
525     Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
526
527     delete mNotificationTrigger;
528     mNotificationTrigger = NULL;
529
530     mCallbackManager->Stop();
531
532     mState = STOPPED;
533
534     DALI_LOG_RELEASE_INFO( "Adaptor::Stop\n" );
535   }
536 }
537
538 void Adaptor::ContextLost()
539 {
540   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
541 }
542
543 void Adaptor::ContextRegained()
544 {
545   // Inform core, so that texture resources can be reloaded
546   mCore->RecoverFromContextLoss();
547
548   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
549 }
550
551 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
552 {
553   Integration::Point convertedPoint( point );
554   mWindows.front()->FeedTouchPoint( convertedPoint, timeStamp );
555 }
556
557 void Adaptor::FeedWheelEvent( Dali::WheelEvent& wheelEvent )
558 {
559   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >( wheelEvent.GetType() ), wheelEvent.GetDirection(), wheelEvent.GetModifiers(), wheelEvent.GetPoint(), wheelEvent.GetDelta(), wheelEvent.GetTime() );
560   mWindows.front()->FeedWheelEvent( event );
561 }
562
563 void Adaptor::FeedKeyEvent( Dali::KeyEvent& keyEvent )
564 {
565   Integration::KeyEvent convertedEvent( keyEvent.GetKeyName(), keyEvent.GetLogicalKey(), keyEvent.GetKeyString(), keyEvent.GetKeyCode(), keyEvent.GetKeyModifier(), keyEvent.GetTime(), static_cast< Integration::KeyEvent::State >( keyEvent.GetState() ), keyEvent.GetCompose(), keyEvent.GetDeviceName(), keyEvent.GetDeviceClass(), keyEvent.GetDeviceSubclass() );
566   mWindows.front()->FeedKeyEvent( convertedEvent );
567 }
568
569 void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface )
570 {
571   Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation( window );
572   for( auto windowPtr : mWindows )
573   {
574     if( windowPtr == windowImpl ) // the window is not deleted
575     {
576       mResizedSignal.Emit( mAdaptor );
577
578       windowImpl->SetSurface( &newSurface );
579
580       // Flush the event queue to give the update-render thread chance
581       // to start processing messages for new camera setup etc as soon as possible
582       ProcessCoreEvents();
583
584       // This method blocks until the render thread has completed the replace.
585       mThreadController->ReplaceSurface( &newSurface );
586       break;
587     }
588   }
589 }
590
591 void Adaptor::DeleteSurface( Dali::RenderSurfaceInterface& surface )
592 {
593   // Flush the event queue to give the update-render thread chance
594   // to start processing messages for new camera setup etc as soon as possible
595   ProcessCoreEvents();
596
597   // This method blocks until the render thread has finished rendering the current surface.
598   mThreadController->DeleteSurface( &surface );
599 }
600
601 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
602 {
603   return *mWindows.front()->GetSurface();
604 }
605
606 void Adaptor::ReleaseSurfaceLock()
607 {
608   mWindows.front()->GetSurface()->ReleaseLock();
609 }
610
611 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
612 {
613   if( !mTtsPlayers[mode] )
614   {
615     // Create the TTS player when it needed, because it can reduce launching time.
616     mTtsPlayers[mode] = TtsPlayer::New(mode);
617   }
618
619   return mTtsPlayers[mode];
620 }
621
622 bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue, bool forceAdd )
623 {
624   bool idleAdded(false);
625
626   // Only add an idle if the Adaptor is actually running
627   if( RUNNING == mState || READY == mState || forceAdd )
628   {
629     idleAdded = mCallbackManager->AddIdleCallback( callback, hasReturnValue );
630   }
631
632   return idleAdded;
633 }
634
635 void Adaptor::RemoveIdle( CallbackBase* callback )
636 {
637   mCallbackManager->RemoveIdleCallback( callback );
638 }
639
640 void Adaptor::ProcessIdle()
641 {
642   bool idleProcessed = mCallbackManager->ProcessIdle();
643   mNotificationOnIdleInstalled = mNotificationOnIdleInstalled && !idleProcessed;
644 }
645
646 void Adaptor::SetPreRenderCallback( CallbackBase* callback )
647 {
648   mThreadController->SetPreRenderCallback( callback );
649 }
650
651 bool Adaptor::AddWindow( Dali::Integration::SceneHolder childWindow )
652 {
653   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( childWindow );
654   windowImpl.SetAdaptor( Get() );
655
656   // ChildWindow is set to the layout direction of the default window.
657   windowImpl.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection );
658
659   // Add the new Window to the container - the order is not important
660   mWindows.push_back( &windowImpl );
661
662   Dali::RenderSurfaceInterface* surface = windowImpl.GetSurface();
663
664   mThreadController->AddSurface( surface );
665
666   mWindowCreatedSignal.Emit( childWindow );
667
668   return true;
669 }
670
671 bool Adaptor::RemoveWindow( Dali::Integration::SceneHolder* childWindow )
672 {
673   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( *childWindow );
674   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
675   {
676     if( *iter == &windowImpl )
677     {
678       mWindows.erase( iter );
679       return true;
680     }
681   }
682
683   return false;
684 }
685
686 bool Adaptor::RemoveWindow( std::string childWindowName )
687 {
688   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
689   {
690     if( ( *iter )->GetName() == childWindowName )
691     {
692       mWindows.erase( iter );
693       return true;
694     }
695   }
696
697   return false;
698 }
699
700 bool Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* childWindow )
701 {
702   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
703   {
704     if( ( *iter )->GetId() == childWindow->GetId() )
705     {
706       mWindows.erase( iter );
707       return true;
708     }
709   }
710
711   return false;
712 }
713
714 Dali::Adaptor& Adaptor::Get()
715 {
716   DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
717   return gThreadLocalAdaptor->mAdaptor;
718 }
719
720 bool Adaptor::IsAvailable()
721 {
722   return gThreadLocalAdaptor != NULL;
723 }
724
725 void Adaptor::SceneCreated()
726 {
727   mCore->SceneCreated();
728 }
729
730 Dali::Integration::Core& Adaptor::GetCore()
731 {
732   return *mCore;
733 }
734
735 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
736 {
737   mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
738 }
739
740 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
741 {
742   DALI_ASSERT_DEBUG( mDisplayConnection && "Display connection not created" );
743   return *mDisplayConnection;
744 }
745
746 GraphicsInterface& Adaptor::GetGraphicsInterface()
747 {
748   DALI_ASSERT_DEBUG( mGraphics && "Graphics interface not created" );
749   return *( mGraphics.get() );
750 }
751
752 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
753 {
754   return *mPlatformAbstraction;
755 }
756
757 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
758 {
759   return *mNotificationTrigger;
760 }
761
762 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
763 {
764   return mSocketFactory;
765 }
766
767 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
768 {
769   if( !mWindows.empty() )
770   {
771     return mWindows.front()->GetSurface();
772   }
773
774   return nullptr;
775 }
776
777 TraceInterface& Adaptor::GetKernelTraceInterface()
778 {
779   return mKernelTracer;
780 }
781
782 TraceInterface& Adaptor::GetSystemTraceInterface()
783 {
784   return mSystemTracer;
785 }
786
787 PerformanceInterface* Adaptor::GetPerformanceInterface()
788 {
789   return mPerformanceInterface;
790 }
791
792 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
793 {
794   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
795   return *mPlatformAbstraction;
796 }
797
798 void Adaptor::GetWindowContainerInterface( WindowContainer& windows )
799 {
800   windows = mWindows;
801 }
802
803 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
804 {
805   if( mTtsPlayers[mode] )
806   {
807     mTtsPlayers[mode].Reset();
808   }
809 }
810
811 Any Adaptor::GetNativeWindowHandle()
812 {
813   return mWindows.front()->GetNativeHandle();
814 }
815
816 Any Adaptor::GetNativeWindowHandle( Dali::Actor actor )
817 {
818   Any nativeWindowHandle;
819
820   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
821
822   for( auto sceneHolder : mWindows )
823   {
824     if ( scene == sceneHolder->GetScene() )
825     {
826       nativeWindowHandle = sceneHolder->GetNativeHandle();
827       break;
828     }
829   }
830
831   return nativeWindowHandle;
832 }
833
834 Any Adaptor::GetGraphicsDisplay()
835 {
836   Any display;
837
838   if (mGraphics)
839   {
840     GraphicsInterface* graphics = mGraphics.get(); // This interface is temporary until Core has been updated to match
841     auto eglGraphics = static_cast<EglGraphics *>( graphics );
842
843     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
844     display = eglImpl.GetDisplay();
845   }
846
847   return display;
848 }
849
850 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
851 {
852   mUseRemoteSurface = useRemoteSurface;
853 }
854
855 void Adaptor::AddObserver( LifeCycleObserver& observer )
856 {
857   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
858
859   if ( match == mObservers.end() )
860   {
861     mObservers.push_back( &observer );
862   }
863 }
864
865 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
866 {
867   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
868
869   if ( match != mObservers.end() )
870   {
871     mObservers.erase( match );
872   }
873 }
874
875 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
876 {
877   if( mCore )
878   {
879     mCore->QueueEvent(event);
880   }
881 }
882
883 void Adaptor::ProcessCoreEvents()
884 {
885   if( mCore )
886   {
887     if( mPerformanceInterface )
888     {
889       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
890     }
891
892     mCore->ProcessEvents();
893
894     if( mPerformanceInterface )
895     {
896       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
897     }
898   }
899 }
900
901 void Adaptor::RequestUpdate( bool forceUpdate )
902 {
903   switch( mState )
904   {
905     case RUNNING:
906     {
907       mThreadController->RequestUpdate();
908       break;
909     }
910     case PAUSED:
911     case PAUSED_WHILE_HIDDEN:
912     {
913       if( forceUpdate )
914       {
915         // Update (and resource upload) without rendering
916         mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
917       }
918       break;
919     }
920     default:
921     {
922       // Do nothing
923       break;
924     }
925   }
926 }
927
928 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
929 {
930   // Only request a notification if the Adaptor is actually running
931   // and we haven't installed the idle notification
932   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
933   {
934     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
935   }
936 }
937
938 void Adaptor::OnWindowShown()
939 {
940   if( PAUSED_WHILE_HIDDEN == mState )
941   {
942     // Adaptor can now be resumed
943     mState = PAUSED;
944
945     Resume();
946
947     // Force a render task
948     RequestUpdateOnce();
949   }
950   else if( RUNNING == mState )
951   {
952     // Force a render task
953     RequestUpdateOnce();
954
955     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
956   }
957   else if( PAUSED_WHILE_INITIALIZING == mState )
958   {
959     // Change the state to READY again. It will be changed to RUNNING after the adaptor is started.
960     mState = READY;
961   }
962   else
963   {
964     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
965   }
966 }
967
968 void Adaptor::OnWindowHidden()
969 {
970   if( RUNNING == mState || READY == mState )
971   {
972     bool allWindowsHidden = true;
973
974     for( auto window : mWindows )
975     {
976       if ( window->IsVisible() )
977       {
978         allWindowsHidden = false;
979         break;
980       }
981     }
982
983     // Only pause the adaptor when all the windows are hidden
984     if( allWindowsHidden )
985     {
986       if( mState == RUNNING )
987       {
988         Pause();
989
990         // Adaptor cannot be resumed until any window is shown
991         mState = PAUSED_WHILE_HIDDEN;
992       }
993       else  // mState is READY
994       {
995         // Pause the adaptor after the state gets RUNNING
996         mState = PAUSED_WHILE_INITIALIZING;
997       }
998     }
999     else
1000     {
1001       DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
1002     }
1003   }
1004   else
1005   {
1006     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
1007   }
1008 }
1009
1010 // Dali::Internal::Adaptor::Adaptor::OnDamaged
1011 void Adaptor::OnDamaged( const DamageArea& area )
1012 {
1013   // This is needed for the case where Dali window is partially obscured
1014   RequestUpdate( false );
1015 }
1016
1017 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
1018 {
1019   mResizedSignal.Emit( mAdaptor );
1020 }
1021
1022 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
1023 {
1024   // Nofify surface resizing before flushing event queue
1025   mThreadController->ResizeSurface();
1026
1027   // Flush the event queue to give the update-render thread chance
1028   // to start processing messages for new camera setup etc as soon as possible
1029   ProcessCoreEvents();
1030 }
1031
1032 void Adaptor::NotifySceneCreated()
1033 {
1034   GetCore().SceneCreated();
1035
1036   // Flush the event queue to give the update-render thread chance
1037   // to start processing messages for new camera setup etc as soon as possible
1038   ProcessCoreEvents();
1039
1040   // Start thread controller after the scene has been created
1041   mThreadController->Start();
1042
1043   // Process after surface is created (registering to remote surface provider if required)
1044   SurfaceInitialized();
1045
1046   if( mState != PAUSED_WHILE_INITIALIZING )
1047   {
1048     mState = RUNNING;
1049
1050     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
1051   }
1052   else
1053   {
1054     mState = RUNNING;
1055
1056     Pause();
1057
1058     mState = PAUSED_WHILE_HIDDEN;
1059
1060     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1061   }
1062 }
1063
1064 void Adaptor::NotifyLanguageChanged()
1065 {
1066   mLanguageChangedSignal.Emit( mAdaptor );
1067 }
1068
1069 void Adaptor::RenderOnce()
1070 {
1071   if( mThreadController )
1072   {
1073     UpdateMode updateMode;
1074     if( mThreadMode == ThreadMode::NORMAL )
1075     {
1076       updateMode = UpdateMode::NORMAL;
1077     }
1078     else
1079     {
1080       updateMode = UpdateMode::FORCE_RENDER;
1081
1082       ProcessCoreEvents();
1083     }
1084     mThreadController->RequestUpdateOnce( updateMode );
1085   }
1086 }
1087
1088 const LogFactoryInterface& Adaptor::GetLogFactory()
1089 {
1090   return *mEnvironmentOptions;
1091 }
1092
1093 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1094 {
1095   GetCore().RegisterProcessor(processor);
1096 }
1097
1098 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1099 {
1100   GetCore().UnregisterProcessor(processor);
1101 }
1102
1103 bool Adaptor::IsMultipleWindowSupported() const
1104 {
1105   return mConfigurationManager->IsMultipleWindowSupported();
1106 }
1107
1108 void Adaptor::RequestUpdateOnce()
1109 {
1110   if( mThreadController )
1111   {
1112     mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1113   }
1114 }
1115
1116 bool Adaptor::ProcessCoreEventsFromIdle()
1117 {
1118   ProcessCoreEvents();
1119
1120   // the idle handle automatically un-installs itself
1121   mNotificationOnIdleInstalled = false;
1122
1123   return false;
1124 }
1125
1126 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1127 {
1128   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1129
1130   for( auto window : mWindows )
1131   {
1132     if ( scene == window->GetScene() )
1133     {
1134       return window;
1135     }
1136   }
1137
1138   return nullptr;
1139 }
1140
1141 Dali::WindowContainer Adaptor::GetWindows() const
1142 {
1143   Dali::WindowContainer windows;
1144
1145   for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1146   {
1147     // Downcast to Dali::Window
1148     Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1149     if ( window )
1150     {
1151       windows.push_back( window );
1152     }
1153   }
1154
1155   return windows;
1156 }
1157
1158 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1159 {
1160   Dali::SceneHolderList sceneHolderList;
1161
1162   for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1163   {
1164     sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1165   }
1166
1167   return sceneHolderList;
1168 }
1169
1170 Dali::ObjectRegistry Adaptor::GetObjectRegistry() const
1171 {
1172   Dali::ObjectRegistry registry;
1173   if( mCore )
1174   {
1175     registry = mCore->GetObjectRegistry();
1176   }
1177   return registry;
1178 }
1179
1180 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1181 : mResizedSignal(),
1182   mLanguageChangedSignal(),
1183   mWindowCreatedSignal(),
1184   mAdaptor( adaptor ),
1185   mState( READY ),
1186   mCore( nullptr ),
1187   mThreadController( nullptr ),
1188   mGraphics( nullptr ),
1189   mDisplayConnection( nullptr ),
1190   mWindows(),
1191   mConfigurationManager( nullptr ),
1192   mPlatformAbstraction( nullptr ),
1193   mCallbackManager( nullptr ),
1194   mNotificationOnIdleInstalled( false ),
1195   mNotificationTrigger( nullptr ),
1196   mDaliFeedbackPlugin(),
1197   mFeedbackController( nullptr ),
1198   mTtsPlayers(),
1199   mObservers(),
1200   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1201   mPerformanceInterface( nullptr ),
1202   mKernelTracer(),
1203   mSystemTracer(),
1204   mObjectProfiler( nullptr ),
1205   mSocketFactory(),
1206   mThreadMode( ThreadMode::NORMAL ),
1207   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1208   mUseRemoteSurface( false ),
1209   mRootLayoutDirection( Dali::LayoutDirection::LEFT_TO_RIGHT )
1210 {
1211   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1212   mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1213
1214   gThreadLocalAdaptor = this;
1215 }
1216
1217 void Adaptor::SetRootLayoutDirection( std::string locale )
1218 {
1219   mRootLayoutDirection = static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) );
1220   for ( auto& window : mWindows )
1221   {
1222     Dali::Actor root = window->GetRootLayer();
1223     root.SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection );
1224   }
1225 }
1226
1227 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1228 {
1229   bool idleAdded( false );
1230
1231   // Only add an idle if the Adaptor is actually running
1232   if( RUNNING == mState || READY == mState || forceAdd )
1233   {
1234     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1235   }
1236
1237   if( !idleAdded )
1238   {
1239     // Delete callback
1240     delete callback;
1241   }
1242
1243   return idleAdded;
1244 }
1245
1246 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1247 {
1248   mCallbackManager->RemoveIdleEntererCallback( callback );
1249 }
1250
1251 } // namespace Adaptor
1252
1253 } // namespace Internal
1254
1255 } // namespace Dali