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