[AT-SPI] Rework intercepting key events
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / adaptor-impl.cpp
1 /*
2  * Copyright (c) 2024 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>
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   // Create TextureUploadManager after mCore created
185   mTextureUploadManager = Dali::Devel::TextureUploadManager::Get();
186
187   defaultWindow->SetAdaptor(Get());
188
189   Dali::Integration::SceneHolder defaultSceneHolder(defaultWindow);
190
191   mWindowCreatedSignal.Emit(defaultSceneHolder);
192
193   const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
194   if(0u < timeInterval)
195   {
196     mObjectProfiler = new ObjectProfiler(mCore->GetObjectRegistry(), timeInterval);
197   }
198
199   const uint32_t poolTimeInterval = mEnvironmentOptions->GetMemoryPoolInterval();
200   if(0u < poolTimeInterval)
201   {
202     mMemoryPoolTimer = Dali::Timer::New(poolTimeInterval * 1000);
203     mMemoryPoolTimer.TickSignal().Connect(mMemoryPoolTimerSlotDelegate, &Adaptor::MemoryPoolTimeout);
204     mMemoryPoolTimer.Start();
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   if(mEnvironmentOptions->GetTapMaximumAllowedTime() > 0)
311   {
312     Integration::SetTapMaximumAllowedTime(mEnvironmentOptions->GetTapMaximumAllowedTime());
313   }
314
315   std::string systemCachePath = GetSystemCachePath();
316   if(!systemCachePath.empty())
317   {
318     const int dir_err = mkdir(systemCachePath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
319     if(0 != dir_err && errno != EEXIST)
320     {
321       DALI_LOG_ERROR("Error creating system cache directory: %s!\n", systemCachePath.c_str());
322     }
323   }
324
325   mConfigurationManager = Utils::MakeUnique<ConfigurationManager>(systemCachePath, mGraphics.get(), mThreadController);
326 }
327
328 Adaptor::~Adaptor()
329 {
330   Accessibility::Bridge::GetCurrentBridge()->Terminate();
331
332   // Ensure stop status
333   Stop();
334
335   // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
336   gThreadLocalAdaptor = NULL;
337
338   for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
339   {
340     (*iter)->OnDestroy();
341   }
342
343   // Clear out all the handles to Windows
344   mWindows.clear();
345
346   delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
347   delete mObjectProfiler;
348
349   delete mCore;
350
351   delete mDisplayConnection;
352   delete mPlatformAbstraction;
353
354   mCallbackManager.reset();
355
356   delete mPerformanceInterface;
357
358   mGraphics->Destroy();
359
360   // uninstall it on this thread (main actor thread)
361   Dali::Integration::Log::UninstallLogFunction();
362
363   // Delete environment options if we own it
364   if(mEnvironmentOptionsOwned)
365   {
366     delete mEnvironmentOptions;
367   }
368 }
369
370 void Adaptor::Start()
371 {
372   // It doesn't support restart after stop at this moment to support restarting, need more testing
373   if(READY != mState)
374   {
375     return;
376   }
377
378   mCore->Initialize();
379
380   SetupSystemInformation();
381
382   // Start the callback manager
383   mCallbackManager->Start();
384
385   // Initialize accessibility bridge after callback manager is started to use Idler callback
386   auto appName = GetApplicationPackageName();
387   auto bridge  = Accessibility::Bridge::GetCurrentBridge();
388   bridge->SetApplicationName(appName);
389   bridge->Initialize();
390
391   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
392
393   unsigned int dpiHor, dpiVer;
394   dpiHor = dpiVer = 0;
395
396   defaultWindow->GetSurface()->GetDpi(dpiHor, dpiVer);
397   Dali::Internal::Adaptor::WindowSystem::SetDpi(dpiHor, dpiVer);
398
399   // Initialize the thread controller
400   mThreadController->Initialize();
401
402   // Set max texture size
403   if(mEnvironmentOptions->GetMaxTextureSize() > 0)
404   {
405     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize(mEnvironmentOptions->GetMaxTextureSize());
406   }
407   else
408   {
409     unsigned int maxTextureSize = mConfigurationManager->GetMaxTextureSize();
410     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize(maxTextureSize);
411   }
412
413   // cache advanced blending and shader language version
414   mGraphics->CacheConfigurations(*mConfigurationManager.get());
415
416   ProcessCoreEvents(); // Ensure any startup messages are processed.
417
418   // Initialize the image loader plugin
419   auto enablePluginString = Dali::EnvironmentVariable::GetEnvironmentVariable(ENABLE_IMAGE_LOADER_PLUGIN_ENV);
420   bool enablePlugin       = enablePluginString ? std::atoi(enablePluginString) : false;
421   if(enablePlugin)
422   {
423     Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
424   }
425
426   for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
427   {
428     (*iter)->OnStart();
429   }
430
431   if(mAddOnManager)
432   {
433     mAddOnManager->Start();
434   }
435 }
436
437 // Dali::Internal::Adaptor::Adaptor::Pause
438 void Adaptor::Pause()
439 {
440   // Only pause the adaptor if we're actually running.
441   if(RUNNING == mState)
442   {
443     // Inform observers that we are about to be paused.
444     for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
445     {
446       (*iter)->OnPause();
447     }
448
449     // Extensions
450     if(mAddOnManager)
451     {
452       mAddOnManager->Pause();
453     }
454
455     // Pause all windows event handlers when adaptor paused
456     for(auto window : mWindows)
457     {
458       window->Pause();
459     }
460
461     mThreadController->Pause();
462     mState = PAUSED;
463
464     // Ensure any messages queued during pause callbacks are processed by doing another update.
465     RequestUpdateOnce();
466
467     DALI_LOG_RELEASE_INFO("Adaptor::Pause: Paused\n");
468   }
469   else
470   {
471     DALI_LOG_RELEASE_INFO("Adaptor::Pause: Not paused [%d]\n", mState);
472   }
473 }
474
475 // Dali::Internal::Adaptor::Adaptor::Resume
476 void Adaptor::Resume()
477 {
478   // Only resume the adaptor if we are in the suspended state.
479   if(PAUSED == mState)
480   {
481     mState = RUNNING;
482
483     // Reset the event handlers when adaptor resumed
484     for(auto window : mWindows)
485     {
486       window->Resume();
487     }
488
489     // Resume AddOnManager
490     if(mAddOnManager)
491     {
492       mAddOnManager->Resume();
493     }
494
495     // Inform observers that we have resumed.
496     for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
497     {
498       (*iter)->OnResume();
499     }
500
501     // Trigger processing of events queued up while paused
502     mCore->ProcessEvents();
503
504     // Do at end to ensure our first update/render after resumption includes the processed messages as well
505     mThreadController->Resume();
506
507     DALI_LOG_RELEASE_INFO("Adaptor::Resume: Resumed\n");
508   }
509   else
510   {
511     DALI_LOG_RELEASE_INFO("Adaptor::Resume: Not resumed [%d]\n", mState);
512   }
513 }
514
515 void Adaptor::Stop()
516 {
517   if(RUNNING == mState ||
518      PAUSED == mState ||
519      PAUSED_WHILE_HIDDEN == mState)
520   {
521     for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
522     {
523       (*iter)->OnStop();
524     }
525
526     if(mAddOnManager)
527     {
528       mAddOnManager->Stop();
529     }
530
531     mThreadController->Stop();
532
533     // Delete the TTS player
534     for(int i = 0; i < Dali::TtsPlayer::MODE_NUM; i++)
535     {
536       if(mTtsPlayers[i])
537       {
538         mTtsPlayers[i].Reset();
539       }
540     }
541
542     // Destroy the image loader plugin
543     auto enablePluginString = Dali::EnvironmentVariable::GetEnvironmentVariable(ENABLE_IMAGE_LOADER_PLUGIN_ENV);
544     bool enablePlugin       = enablePluginString ? std::atoi(enablePluginString) : false;
545     if(enablePlugin)
546     {
547       Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
548     }
549
550     delete mNotificationTrigger;
551     mNotificationTrigger = NULL;
552
553     mCallbackManager->Stop();
554
555     mState = STOPPED;
556
557     RemoveSystemInformation();
558
559     DALI_LOG_RELEASE_INFO("Adaptor::Stop\n");
560   }
561 }
562
563 void Adaptor::ContextLost()
564 {
565   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
566 }
567
568 void Adaptor::ContextRegained()
569 {
570   // Inform core, so that texture resources can be reloaded
571   mCore->RecoverFromContextLoss();
572
573   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
574 }
575
576 void Adaptor::FeedTouchPoint(TouchPoint& point, int timeStamp)
577 {
578   Integration::Point convertedPoint(point);
579   mWindows.front()->FeedTouchPoint(convertedPoint, timeStamp);
580 }
581
582 void Adaptor::FeedWheelEvent(Dali::WheelEvent& wheelEvent)
583 {
584   Integration::WheelEvent event(static_cast<Integration::WheelEvent::Type>(wheelEvent.GetType()), wheelEvent.GetDirection(), wheelEvent.GetModifiers(), wheelEvent.GetPoint(), wheelEvent.GetDelta(), wheelEvent.GetTime());
585   mWindows.front()->FeedWheelEvent(event);
586 }
587
588 void Adaptor::FeedKeyEvent(Dali::KeyEvent& keyEvent)
589 {
590   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());
591   mWindows.front()->FeedKeyEvent(convertedEvent);
592 }
593
594 void Adaptor::ReplaceSurface(Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface)
595 {
596   Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation(window);
597   for(auto windowPtr : mWindows)
598   {
599     if(windowPtr == windowImpl) // the window is not deleted
600     {
601       mResizedSignal.Emit(mAdaptor);
602
603       windowImpl->SetSurface(&newSurface);
604
605       // Flush the event queue to give the update-render thread chance
606       // to start processing messages for new camera setup etc as soon as possible
607       ProcessCoreEvents();
608
609       // This method blocks until the render thread has completed the replace.
610       mThreadController->ReplaceSurface(&newSurface);
611       break;
612     }
613   }
614 }
615
616 void Adaptor::DeleteSurface(Dali::RenderSurfaceInterface& surface)
617 {
618   // Flush the event queue to give the update-render thread chance
619   // to start processing messages for new camera setup etc as soon as possible
620   ProcessCoreEvents();
621
622   // This method blocks until the render thread has finished rendering the current surface.
623   mThreadController->DeleteSurface(&surface);
624 }
625
626 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
627 {
628   return *mWindows.front()->GetSurface();
629 }
630
631 void Adaptor::ReleaseSurfaceLock()
632 {
633   mWindows.front()->GetSurface()->ReleaseLock();
634 }
635
636 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
637 {
638   if(!mTtsPlayers[mode])
639   {
640     // Create the TTS player when it needed, because it can reduce launching time.
641     mTtsPlayers[mode] = TtsPlayer::New(mode);
642   }
643
644   return mTtsPlayers[mode];
645 }
646
647 bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue)
648 {
649   bool idleAdded(false);
650
651   // We want to run the processes even when paused
652   if(STOPPED != mState)
653   {
654     idleAdded = mCallbackManager->AddIdleCallback(callback, hasReturnValue);
655   }
656
657   if(!idleAdded)
658   {
659     // Delete callback
660     delete callback;
661   }
662
663   return idleAdded;
664 }
665
666 void Adaptor::RemoveIdle(CallbackBase* callback)
667 {
668   mCallbackManager->RemoveIdleCallback(callback);
669 }
670
671 void Adaptor::ProcessIdle()
672 {
673   bool idleProcessed           = mCallbackManager->ProcessIdle();
674   mNotificationOnIdleInstalled = mNotificationOnIdleInstalled && !idleProcessed;
675 }
676
677 void Adaptor::SetPreRenderCallback(CallbackBase* callback)
678 {
679   mThreadController->SetPreRenderCallback(callback);
680 }
681
682 bool Adaptor::AddWindow(Dali::Integration::SceneHolder childWindow)
683 {
684   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(childWindow);
685   windowImpl.SetAdaptor(Get());
686
687   // ChildWindow is set to the layout direction of the default window.
688   windowImpl.GetRootLayer().SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection);
689
690   // Add the new Window to the container - the order is not important
691   {
692     Dali::Mutex::ScopedLock lock(mMutex);
693     mWindows.push_back(&windowImpl);
694   }
695
696   Dali::RenderSurfaceInterface* surface = windowImpl.GetSurface();
697
698   mThreadController->AddSurface(surface);
699
700   mWindowCreatedSignal.Emit(childWindow);
701
702   return true;
703 }
704
705 bool Adaptor::RemoveWindow(Dali::Integration::SceneHolder* childWindow)
706 {
707   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(*childWindow);
708   for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
709   {
710     if(*iter == &windowImpl)
711     {
712       Dali::Mutex::ScopedLock lock(mMutex);
713       mWindows.erase(iter);
714       return true;
715     }
716   }
717
718   return false;
719 }
720
721 bool Adaptor::RemoveWindow(std::string childWindowName)
722 {
723   for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
724   {
725     if((*iter)->GetName() == childWindowName)
726     {
727       Dali::Mutex::ScopedLock lock(mMutex);
728       mWindows.erase(iter);
729       return true;
730     }
731   }
732
733   return false;
734 }
735
736 bool Adaptor::RemoveWindow(Internal::Adaptor::SceneHolder* childWindow)
737 {
738   for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
739   {
740     if((*iter)->GetId() == childWindow->GetId())
741     {
742       Dali::Mutex::ScopedLock lock(mMutex);
743       mWindows.erase(iter);
744       return true;
745     }
746   }
747
748   return false;
749 }
750
751 Dali::Adaptor& Adaptor::Get()
752 {
753   DALI_ASSERT_ALWAYS(IsAvailable() && "Adaptor not instantiated");
754   return gThreadLocalAdaptor->mAdaptor;
755 }
756
757 bool Adaptor::IsAvailable()
758 {
759   return gThreadLocalAdaptor != NULL;
760 }
761
762 void Adaptor::SceneCreated()
763 {
764   mCore->SceneCreated();
765 }
766
767 Dali::Integration::Core& Adaptor::GetCore()
768 {
769   return *mCore;
770 }
771
772 void Adaptor::SetRenderRefreshRate(unsigned int numberOfVSyncsPerRender)
773 {
774   mThreadController->SetRenderRefreshRate(numberOfVSyncsPerRender);
775 }
776
777 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
778 {
779   DALI_ASSERT_DEBUG(mDisplayConnection && "Display connection not created");
780   return *mDisplayConnection;
781 }
782
783 GraphicsInterface& Adaptor::GetGraphicsInterface()
784 {
785   DALI_ASSERT_DEBUG(mGraphics && "Graphics interface not created");
786   return *(mGraphics.get());
787 }
788
789 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
790 {
791   return *mPlatformAbstraction;
792 }
793
794 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
795 {
796   return *mNotificationTrigger;
797 }
798
799 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
800 {
801   return mSocketFactory;
802 }
803
804 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
805 {
806   if(!mWindows.empty())
807   {
808     return mWindows.front()->GetSurface();
809   }
810
811   return nullptr;
812 }
813
814 TraceInterface& Adaptor::GetKernelTraceInterface()
815 {
816   return mKernelTracer;
817 }
818
819 TraceInterface& Adaptor::GetSystemTraceInterface()
820 {
821   return mSystemTracer;
822 }
823
824 PerformanceInterface* Adaptor::GetPerformanceInterface()
825 {
826   return mPerformanceInterface;
827 }
828
829 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
830 {
831   DALI_ASSERT_DEBUG(mPlatformAbstraction && "PlatformAbstraction not created");
832   return *mPlatformAbstraction;
833 }
834
835 void Adaptor::GetWindowContainerInterface(WindowContainer& windows)
836 {
837   Dali::Mutex::ScopedLock lock(mMutex);
838   windows = mWindows;
839 }
840
841 Devel::TextureUploadManager& Adaptor::GetTextureUploadManager()
842 {
843   return mTextureUploadManager;
844 }
845
846 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
847 {
848   if(mTtsPlayers[mode])
849   {
850     mTtsPlayers[mode].Reset();
851   }
852 }
853
854 Any Adaptor::GetNativeWindowHandle()
855 {
856   return mWindows.front()->GetNativeHandle();
857 }
858
859 Any Adaptor::GetNativeWindowHandle(Dali::Actor actor)
860 {
861   Any nativeWindowHandle;
862
863   Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
864
865   for(auto sceneHolder : mWindows)
866   {
867     if(scene == sceneHolder->GetScene())
868     {
869       nativeWindowHandle = sceneHolder->GetNativeHandle();
870       break;
871     }
872   }
873
874   return nativeWindowHandle;
875 }
876
877 Any Adaptor::GetGraphicsDisplay()
878 {
879   Any display;
880
881   if(mGraphics)
882   {
883     GraphicsInterface* graphics    = mGraphics.get(); // This interface is temporary until Core has been updated to match
884     auto               eglGraphics = static_cast<EglGraphics*>(graphics);
885
886     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
887     display                    = eglImpl.GetDisplay();
888   }
889
890   return display;
891 }
892
893 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
894 {
895   mUseRemoteSurface = useRemoteSurface;
896 }
897
898 void Adaptor::AddObserver(LifeCycleObserver& observer)
899 {
900   ObserverContainer::iterator match(find(mObservers.begin(), mObservers.end(), &observer));
901
902   if(match == mObservers.end())
903   {
904     mObservers.push_back(&observer);
905   }
906 }
907
908 void Adaptor::RemoveObserver(LifeCycleObserver& observer)
909 {
910   ObserverContainer::iterator match(find(mObservers.begin(), mObservers.end(), &observer));
911
912   if(match != mObservers.end())
913   {
914     mObservers.erase(match);
915   }
916 }
917
918 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
919 {
920   if(mCore)
921   {
922     mCore->QueueEvent(event);
923   }
924 }
925
926 void Adaptor::FlushUpdateMessages()
927 {
928   if(mCore)
929   {
930     DALI_TRACE_SCOPE(gTraceFilter, "DALI_FLUSH_UPDATE_MESSAGES");
931
932     mCore->ForceRelayout();
933   }
934 }
935
936 void Adaptor::ProcessCoreEvents()
937 {
938   if(mCore)
939   {
940     DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_CORE_EVENTS");
941
942     if(mPerformanceInterface)
943     {
944       mPerformanceInterface->AddMarker(PerformanceInterface::PROCESS_EVENTS_START);
945     }
946
947     mCore->ProcessEvents();
948
949     if(mPerformanceInterface)
950     {
951       mPerformanceInterface->AddMarker(PerformanceInterface::PROCESS_EVENTS_END);
952     }
953   }
954 }
955
956 void Adaptor::RequestUpdate()
957 {
958   switch(mState)
959   {
960     case RUNNING:
961     {
962       mThreadController->RequestUpdate();
963       break;
964     }
965     case PAUSED:
966     case PAUSED_WHILE_HIDDEN:
967     {
968       // Update (and resource upload) without rendering
969       mThreadController->RequestUpdateOnce(UpdateMode::SKIP_RENDER);
970       break;
971     }
972     default:
973     {
974       // Do nothing
975       break;
976     }
977   }
978 }
979
980 void Adaptor::RequestProcessEventsOnIdle()
981 {
982   // We want to run the processes even when paused
983   if(STOPPED != mState)
984   {
985     if(!mNotificationOnIdleInstalled)
986     {
987       // If we haven't installed the idle notification, install it idle enterer.
988       mNotificationOnIdleInstalled = AddIdleEnterer(MakeCallback(this, &Adaptor::ProcessCoreEventsFromIdle));
989     }
990     else
991     {
992       // Request comes during ProcessCoreEventsFromIdle running.
993       // Mark as we need to call ProcessEvents in next idle events.
994       mRequiredIdleRepeat = true;
995     }
996   }
997 }
998
999 void Adaptor::OnWindowShown()
1000 {
1001   if(PAUSED_WHILE_HIDDEN == mState)
1002   {
1003     // Adaptor can now be resumed
1004     mState = PAUSED;
1005
1006     Resume();
1007
1008     // Force a render task
1009     RequestUpdateOnce();
1010   }
1011   else if(RUNNING == mState)
1012   {
1013     // Force a render task
1014     RequestUpdateOnce();
1015
1016     DALI_LOG_RELEASE_INFO("Adaptor::OnWindowShown: Update requested.\n");
1017   }
1018   else if(PAUSED_WHILE_INITIALIZING == mState)
1019   {
1020     // Change the state to READY again. It will be changed to RUNNING after the adaptor is started.
1021     mState = READY;
1022   }
1023   else
1024   {
1025     DALI_LOG_RELEASE_INFO("Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState);
1026   }
1027 }
1028
1029 void Adaptor::OnWindowHidden()
1030 {
1031   if(RUNNING == mState || READY == mState)
1032   {
1033     bool allWindowsHidden = true;
1034
1035     for(auto window : mWindows)
1036     {
1037       if(window->IsVisible())
1038       {
1039         allWindowsHidden = false;
1040         break;
1041       }
1042     }
1043
1044     // Only pause the adaptor when all the windows are hidden
1045     if(allWindowsHidden)
1046     {
1047       if(mState == RUNNING)
1048       {
1049         Pause();
1050
1051         // Adaptor cannot be resumed until any window is shown
1052         mState = PAUSED_WHILE_HIDDEN;
1053       }
1054       else // mState is READY
1055       {
1056         // Pause the adaptor after the state gets RUNNING
1057         mState = PAUSED_WHILE_INITIALIZING;
1058       }
1059     }
1060     else
1061     {
1062       DALI_LOG_RELEASE_INFO("Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n");
1063     }
1064   }
1065   else
1066   {
1067     DALI_LOG_RELEASE_INFO("Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState);
1068   }
1069 }
1070
1071 // Dali::Internal::Adaptor::Adaptor::OnDamaged
1072 void Adaptor::OnDamaged(const DamageArea& area)
1073 {
1074   // This is needed for the case where Dali window is partially obscured
1075   RequestUpdate();
1076 }
1077
1078 void Adaptor::SurfaceResizePrepare(Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize)
1079 {
1080   mResizedSignal.Emit(mAdaptor);
1081 }
1082
1083 void Adaptor::SurfaceResizeComplete(Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize)
1084 {
1085   // Nofify surface resizing before flushing event queue
1086   mThreadController->ResizeSurface();
1087
1088   // Flush the event queue to give the update-render thread chance
1089   // to start processing messages for new camera setup etc as soon as possible
1090   ProcessCoreEvents();
1091 }
1092
1093 void Adaptor::IncreaseSurfaceResizeCounter()
1094 {
1095   // Nofify surface resizing before flushing event queue
1096   if(mThreadController)
1097   {
1098     mThreadController->ResizeSurface();
1099   }
1100 }
1101
1102 void Adaptor::NotifySceneCreated()
1103 {
1104   GetCore().SceneCreated();
1105
1106   // Flush the event queue to give the update-render thread chance
1107   // to start processing messages for new camera setup etc as soon as possible
1108   ProcessCoreEvents();
1109
1110   // Start thread controller after the scene has been created
1111   mThreadController->Start();
1112
1113   // Process after surface is created (registering to remote surface provider if required)
1114   SurfaceInitialized();
1115
1116   if(mState != PAUSED_WHILE_INITIALIZING)
1117   {
1118     mState = RUNNING;
1119
1120     DALI_LOG_RELEASE_INFO("Adaptor::NotifySceneCreated: Adaptor is running\n");
1121   }
1122   else
1123   {
1124     mState = RUNNING;
1125
1126     Pause();
1127
1128     mState = PAUSED_WHILE_HIDDEN;
1129
1130     DALI_LOG_RELEASE_INFO("Adaptor::NotifySceneCreated: Adaptor is paused\n");
1131   }
1132 }
1133
1134 void Adaptor::NotifyLanguageChanged()
1135 {
1136   mLanguageChangedSignal.Emit(mAdaptor);
1137 }
1138
1139 void Adaptor::RenderOnce()
1140 {
1141   if(mThreadController)
1142   {
1143     UpdateMode updateMode;
1144     if(mThreadMode == ThreadMode::NORMAL)
1145     {
1146       updateMode = UpdateMode::NORMAL;
1147     }
1148     else
1149     {
1150       updateMode = UpdateMode::FORCE_RENDER;
1151
1152       ProcessCoreEvents();
1153     }
1154
1155     // Force rendering
1156     for(auto&& iter : mWindows)
1157     {
1158       iter->GetSurface()->SetFullSwapNextFrame();
1159     }
1160
1161     mThreadController->RequestUpdateOnce(updateMode);
1162   }
1163 }
1164
1165 const LogFactoryInterface& Adaptor::GetLogFactory()
1166 {
1167   return *mEnvironmentOptions;
1168 }
1169
1170 const TraceFactoryInterface& Adaptor::GetTraceFactory()
1171 {
1172   return *mEnvironmentOptions;
1173 }
1174
1175 void Adaptor::RegisterProcessor(Integration::Processor& processor, bool postProcessor)
1176 {
1177   GetCore().RegisterProcessor(processor, postProcessor);
1178 }
1179
1180 void Adaptor::UnregisterProcessor(Integration::Processor& processor, bool postProcessor)
1181 {
1182   GetCore().UnregisterProcessor(processor, postProcessor);
1183 }
1184
1185 bool Adaptor::IsMultipleWindowSupported() const
1186 {
1187   return mConfigurationManager->IsMultipleWindowSupported();
1188 }
1189
1190 int32_t Adaptor::GetRenderThreadId() const
1191 {
1192   if(mThreadController)
1193   {
1194     return mThreadController->GetThreadId();
1195   }
1196   return 0;
1197 }
1198
1199 void Adaptor::RequestUpdateOnce()
1200 {
1201   if(mThreadController)
1202   {
1203     mThreadController->RequestUpdateOnce(UpdateMode::NORMAL);
1204   }
1205 }
1206
1207 bool Adaptor::ProcessCoreEventsFromIdle()
1208 {
1209   // Reset repeat idler flag.
1210   mRequiredIdleRepeat = false;
1211   ProcessCoreEvents();
1212
1213   // If someone request ProcessCoreEvents during above ProcessCoreEvents call, we might need to run idle one more times.
1214   // Else, the idle handle automatically un-installs itself
1215   mNotificationOnIdleInstalled = mRequiredIdleRepeat;
1216
1217   if(mRequiredIdleRepeat)
1218   {
1219     DALI_LOG_DEBUG_INFO("Required ProcessCoreEvents one more times\n");
1220   }
1221
1222   return mRequiredIdleRepeat;
1223 }
1224
1225 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow(Dali::Actor& actor)
1226 {
1227   Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
1228
1229   for(auto window : mWindows)
1230   {
1231     if(scene == window->GetScene())
1232     {
1233       return window;
1234     }
1235   }
1236
1237   return nullptr;
1238 }
1239
1240 Dali::WindowContainer Adaptor::GetWindows() const
1241 {
1242   Dali::WindowContainer windows;
1243
1244   for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
1245   {
1246     // Downcast to Dali::Window
1247     Dali::Window window(dynamic_cast<Dali::Internal::Adaptor::Window*>(*iter));
1248     if(window)
1249     {
1250       windows.push_back(window);
1251     }
1252   }
1253
1254   return windows;
1255 }
1256
1257 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1258 {
1259   Dali::SceneHolderList sceneHolderList;
1260
1261   for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
1262   {
1263     sceneHolderList.push_back(Dali::Integration::SceneHolder(*iter));
1264   }
1265
1266   return sceneHolderList;
1267 }
1268
1269 Dali::ObjectRegistry Adaptor::GetObjectRegistry() const
1270 {
1271   Dali::ObjectRegistry registry;
1272   if(mCore)
1273   {
1274     registry = mCore->GetObjectRegistry();
1275   }
1276   return registry;
1277 }
1278
1279 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions, ThreadMode threadMode)
1280 : mResizedSignal(),
1281   mLanguageChangedSignal(),
1282   mWindowCreatedSignal(),
1283   mAdaptor(adaptor),
1284   mState(READY),
1285   mCore(nullptr),
1286   mThreadController(nullptr),
1287   mGraphics(nullptr),
1288   mDisplayConnection(nullptr),
1289   mWindows(),
1290   mConfigurationManager(nullptr),
1291   mPlatformAbstraction(nullptr),
1292   mCallbackManager(nullptr),
1293   mNotificationOnIdleInstalled(false),
1294   mRequiredIdleRepeat(false),
1295   mNotificationTrigger(nullptr),
1296   mDaliFeedbackPlugin(),
1297   mFeedbackController(nullptr),
1298   mTtsPlayers(),
1299   mObservers(),
1300   mEnvironmentOptions(environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1301   mPerformanceInterface(nullptr),
1302   mKernelTracer(),
1303   mSystemTracer(),
1304   mTextureUploadManager(),
1305   mObjectProfiler(nullptr),
1306   mMemoryPoolTimerSlotDelegate(this),
1307   mSocketFactory(),
1308   mMutex(),
1309   mThreadMode(threadMode),
1310   mEnvironmentOptionsOwned(environmentOptions ? false : true /* If not provided then we own the object */),
1311   mUseRemoteSurface(false),
1312   mRootLayoutDirection(Dali::LayoutDirection::LEFT_TO_RIGHT)
1313 {
1314   DALI_ASSERT_ALWAYS(!IsAvailable() && "Cannot create more than one Adaptor per thread");
1315   mWindows.insert(mWindows.begin(), &Dali::GetImplementation(window));
1316
1317   gThreadLocalAdaptor = this;
1318 }
1319
1320 void Adaptor::SetRootLayoutDirection(std::string locale)
1321 {
1322   mRootLayoutDirection = static_cast<LayoutDirection::Type>(Internal::Adaptor::Locale::GetDirection(std::string(locale)));
1323   for(auto& window : mWindows)
1324   {
1325     Dali::Actor root = window->GetRootLayer();
1326     root.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection);
1327   }
1328 }
1329
1330 bool Adaptor::AddIdleEnterer(CallbackBase* callback)
1331 {
1332   bool idleAdded(false);
1333
1334   // We want to run the processes even when paused
1335   if(STOPPED != mState)
1336   {
1337     idleAdded = mCallbackManager->AddIdleEntererCallback(callback);
1338   }
1339
1340   if(!idleAdded)
1341   {
1342     // Delete callback
1343     delete callback;
1344   }
1345
1346   return idleAdded;
1347 }
1348
1349 void Adaptor::RemoveIdleEnterer(CallbackBase* callback)
1350 {
1351   mCallbackManager->RemoveIdleEntererCallback(callback);
1352 }
1353
1354 bool Adaptor::MemoryPoolTimeout()
1355 {
1356   mCore->LogMemoryPools();
1357   return true; // Keep logging forever
1358 }
1359
1360 } // namespace Adaptor
1361
1362 } // namespace Internal
1363
1364 } // namespace Dali