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