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