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