Refactor and add Wayland support.
[platform/core/uifw/dali-adaptor.git] / adaptors / common / adaptor-impl.cpp
1 /*
2  * Copyright (c) 2014 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 "adaptor-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <boost/thread/tss.hpp>
23 #include <dali/public-api/common/dali-common.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/integration-api/core.h>
26 #include <dali/integration-api/profiling.h>
27 #include <dali/integration-api/input-options.h>
28 #include <dali/integration-api/events/touch-event-integ.h>
29
30 // INTERNAL INCLUDES
31 #include <base/update-render-controller.h>
32 #include <base/environment-variables.h>
33 #include <base/performance-logging/performance-interface-factory.h>
34 #include <base/lifecycle-observer.h>
35
36 #include <callback-manager.h>
37 #include <trigger-event.h>
38 #include <render-surface-impl.h>
39 #include <tts-player-impl.h>
40 #include <accessibility-manager-impl.h>
41 #include <timer-impl.h>
42 #include <events/gesture-manager.h>
43 #include <events/event-handler.h>
44 #include <feedback/feedback-controller.h>
45 #include <feedback/feedback-plugin-proxy.h>
46 #include <gl/gl-proxy-implementation.h>
47 #include <gl/gl-implementation.h>
48 #include <gl/egl-sync-implementation.h>
49 #include <gl/egl-image-extensions.h>
50 #include <gl/egl-factory.h>
51 #include <imf-manager-impl.h>
52 #include <clipboard-impl.h>
53 #include <vsync-monitor.h>
54 #include <object-profiler.h>
55
56 #include <slp-logging.h>
57
58
59
60 namespace Dali
61 {
62
63 namespace Internal
64 {
65
66 namespace Adaptor
67 {
68
69 namespace
70 {
71 boost::thread_specific_ptr<Adaptor> gThreadLocalAdaptor;
72
73 unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue )
74 {
75   const char* variableParameter = std::getenv(variable);
76
77   // if the parameter exists convert it to an integer, else return the default value
78   unsigned int intValue = variableParameter ? atoi(variableParameter) : defaultValue;
79   return intValue;
80 }
81
82 bool GetIntegerEnvironmentVariable( const char* variable, int& intValue )
83 {
84   const char* variableParameter = std::getenv(variable);
85
86   if( !variableParameter )
87   {
88     return false;
89   }
90   // if the parameter exists convert it to an integer, else return the default value
91   intValue = atoi(variableParameter);
92   return true;
93 }
94
95 bool GetBooleanEnvironmentVariable( const char* variable, bool& boolValue )
96 {
97   const char* variableParameter = std::getenv(variable);
98
99   boolValue = variableParameter ? true : false;
100   return boolValue;
101 }
102
103 bool GetFloatEnvironmentVariable( const char* variable, float& floatValue )
104 {
105   const char* variableParameter = std::getenv(variable);
106
107   if( !variableParameter )
108   {
109     return false;
110   }
111   // if the parameter exists convert it to an integer, else return the default value
112   floatValue = atof(variableParameter);
113   return true;
114 }
115
116 } // unnamed namespace
117
118 Dali::Adaptor* Adaptor::New( RenderSurface *surface, const DeviceLayout& baseLayout )
119 {
120   DALI_ASSERT_ALWAYS( surface->GetType() != Dali::RenderSurface::NO_SURFACE && "No surface for adaptor" );
121
122   Dali::Adaptor* adaptor = new Dali::Adaptor;
123   Adaptor* impl = new Adaptor( *adaptor, surface, baseLayout );
124   adaptor->mImpl = impl;
125
126   impl->Initialize();
127
128   return adaptor;
129 }
130
131 void Adaptor::ParseEnvironmentOptions()
132 {
133   // get logging options
134   unsigned int logFrameRateFrequency = GetIntegerEnvironmentVariable( DALI_ENV_FPS_TRACKING, 0 );
135   unsigned int logupdateStatusFrequency = GetIntegerEnvironmentVariable( DALI_ENV_UPDATE_STATUS_INTERVAL, 0 );
136   unsigned int logPerformanceLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE, 0 );
137   unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
138
139   // all threads here (event, update, and render) will send their logs to SLP Platform's LogMessage handler.
140   Dali::Integration::Log::LogFunction  logFunction(Dali::SlpPlatform::LogMessage);
141
142   mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceLevel, logPanGesture );
143
144   int predictionMode;
145   if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
146   {
147     mEnvironmentOptions.SetPanGesturePredictionMode(predictionMode);
148   }
149   int predictionAmount = -1;
150   if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_AMOUNT, predictionAmount) )
151   {
152     if( predictionAmount < 0 )
153     {
154       // do not support times in the past
155       predictionAmount = 0;
156     }
157     mEnvironmentOptions.SetPanGesturePredictionAmount(predictionAmount);
158   }
159   int smoothingMode;
160   if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_MODE, smoothingMode) )
161   {
162     mEnvironmentOptions.SetPanGestureSmoothingMode(smoothingMode);
163   }
164   float smoothingAmount = 1.0f;
165   if( GetFloatEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_AMOUNT, smoothingAmount) )
166   {
167     smoothingAmount = Clamp(smoothingAmount, 0.0f, 1.0f);
168     mEnvironmentOptions.SetPanGestureSmoothingAmount(smoothingAmount);
169   }
170
171   int minimumDistance(-1);
172   if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_DISTANCE, minimumDistance ))
173   {
174     mEnvironmentOptions.SetMinimumPanDistance( minimumDistance );
175   }
176
177   int minimumEvents(-1);
178   if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_EVENTS, minimumEvents ))
179   {
180     mEnvironmentOptions.SetMinimumPanEvents( minimumEvents );
181   }
182
183   int glesCallTime(0);
184   if ( GetIntegerEnvironmentVariable(DALI_GLES_CALL_TIME, glesCallTime ))
185   {
186     mEnvironmentOptions.SetGlesCallTime( glesCallTime );
187   }
188
189   mEnvironmentOptions.InstallLogFunction();
190 }
191
192 void Adaptor::Initialize()
193 {
194   ParseEnvironmentOptions();
195
196   mPlatformAbstraction = new SlpPlatform::SlpPlatformAbstraction;
197
198   if( mEnvironmentOptions.GetPerformanceLoggingLevel() > 0 )
199   {
200     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
201   }
202
203   mCallbackManager = CallbackManager::New();
204
205   PositionSize size = mSurface->GetPositionSize();
206
207   mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, mEnvironmentOptions);
208
209   if( mEnvironmentOptions.GetGlesCallTime() > 0 )
210   {
211     mGLES = new GlProxyImplementation( mEnvironmentOptions );
212   }
213   else
214   {
215     mGLES = new GlImplementation();
216   }
217
218   mEglFactory = new EglFactory();
219
220   EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
221
222   mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager );
223
224   mObjectProfiler = new ObjectProfiler();
225
226   mNotificationTrigger = new TriggerEvent( boost::bind(&Adaptor::ProcessCoreEvents, this) );
227
228   mVSyncMonitor = new VSyncMonitor;
229
230   mUpdateRenderController = new UpdateRenderController( *this, mEnvironmentOptions );
231
232   mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
233
234   // Should be called after Core creation
235   if( mEnvironmentOptions.GetPanGestureLoggingLevel() )
236   {
237     Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
238   }
239   if( mEnvironmentOptions.GetPanGesturePredictionMode() >= 0 )
240   {
241     Integration::SetPanGesturePredictionMode(mEnvironmentOptions.GetPanGesturePredictionMode());
242   }
243   if( mEnvironmentOptions.GetPanGesturePredictionAmount() >= 0.0f )
244   {
245     Integration::SetPanGesturePredictionAmount(mEnvironmentOptions.GetPanGesturePredictionAmount());
246   }
247   if( mEnvironmentOptions.GetPanGestureSmoothingMode() >= 0 )
248   {
249     Integration::SetPanGestureSmoothingMode(mEnvironmentOptions.GetPanGestureSmoothingMode());
250   }
251   if( mEnvironmentOptions.GetPanGestureSmoothingAmount() >= 0.0f )
252   {
253     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions.GetPanGestureSmoothingAmount());
254   }
255 }
256
257 Adaptor::~Adaptor()
258 {
259   // Ensure stop status
260   Stop();
261
262   // Release first as we do not want any access to Adaptor as it is being destroyed.
263   gThreadLocalAdaptor.release();
264
265   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
266   {
267     (*iter)->OnDestroy();
268   }
269
270   delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
271   delete mVSyncMonitor;
272   delete mEventHandler;
273   delete mObjectProfiler;
274
275   delete mCore;
276   delete mEglFactory;
277   // Delete feedback controller before feedback plugin & style monitor dependencies
278   delete mFeedbackController;
279   delete mDaliFeedbackPlugin;
280   delete mGLES;
281   delete mGestureManager;
282   delete mPlatformAbstraction;
283   delete mCallbackManager;
284   delete mPerformanceInterface;
285
286   // uninstall it on this thread (main actor thread)
287   Dali::Integration::Log::UninstallLogFunction();
288 }
289
290 void Adaptor::Start()
291 {
292   // it doesn't support restart after stop at this moment
293   // to support restarting, need more testing
294   if( READY != mState )
295   {
296     return;
297   }
298
299   // Start the callback manager
300   mCallbackManager->Start();
301
302   // create event handler
303   mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
304
305   if( mDeferredRotationObserver != NULL )
306   {
307     mEventHandler->SetRotationObserver(mDeferredRotationObserver);
308     mDeferredRotationObserver = NULL;
309   }
310
311   // guarantee map the surface before starting render-thread.
312   mSurface->Map();
313
314   // NOTE: dpi must be set before starting the render thread
315   // use default or command line settings if not run on device
316 #ifdef __arm__
317   // set the DPI value for font rendering
318   unsigned int dpiHor, dpiVer;
319   dpiHor = dpiVer = 0;
320   mSurface->GetDpi(dpiHor, dpiVer);
321
322   // tell core about the value
323   mCore->SetDpi(dpiHor, dpiVer);
324 #else
325   mCore->SetDpi(mHDpi, mVDpi);
326 #endif
327
328   // Tell the core the size of the surface just before we start the render-thread
329   PositionSize size = mSurface->GetPositionSize();
330   mCore->SurfaceResized( size.width, size.height );
331
332   // Start the update & render threads
333   mUpdateRenderController->Start();
334
335   mState = RUNNING;
336
337   ProcessCoreEvents(); // Ensure any startup messages are processed.
338
339   if ( !mFeedbackController )
340   {
341     // Start sound & haptic feedback
342     mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
343   }
344
345   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
346   {
347     (*iter)->OnStart();
348   }
349 }
350
351 // Dali::Internal::Adaptor::Adaptor::Pause
352 void Adaptor::Pause()
353 {
354   // Only pause the adaptor if we're actually running.
355   if( RUNNING == mState )
356   {
357     // Inform observers that we are about to be paused.
358     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
359     {
360       (*iter)->OnPause();
361     }
362
363     // Reset the event handler when adaptor paused
364     if( mEventHandler )
365     {
366       mEventHandler->Reset();
367     }
368
369     mUpdateRenderController->Pause();
370     mCore->Suspend();
371     mState = PAUSED;
372   }
373 }
374
375 // Dali::Internal::Adaptor::Adaptor::Resume
376 void Adaptor::Resume()
377 {
378   // Only resume the adaptor if we are in the suspended state.
379   if( PAUSED == mState )
380   {
381     mCore->Resume();
382     mUpdateRenderController->Resume();
383     mState = RUNNING;
384
385     // Reset the event handler when adaptor resumed
386     if( mEventHandler )
387     {
388       mEventHandler->Reset();
389     }
390
391     // Inform observers that we have resumed.
392     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
393     {
394       (*iter)->OnResume();
395     }
396
397     ProcessCoreEvents(); // Ensure any outstanding messages are processed
398   }
399 }
400
401 void Adaptor::Stop()
402 {
403   if( RUNNING == mState ||
404       PAUSED  == mState ||
405       PAUSED_WHILE_HIDDEN == mState )
406   {
407     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
408     {
409       (*iter)->OnStop();
410     }
411
412     mUpdateRenderController->Stop();
413     mCore->Suspend();
414
415     // Delete the TTS player
416     for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
417     {
418       if(mTtsPlayers[i])
419       {
420         mTtsPlayers[i].Reset();
421       }
422     }
423
424     delete mEventHandler;
425     mEventHandler = NULL;
426
427     delete mNotificationTrigger;
428     mNotificationTrigger = NULL;
429
430     mCallbackManager->Stop();
431
432     mState = STOPPED;
433   }
434 }
435
436 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
437 {
438   mEventHandler->FeedTouchPoint( point, timeStamp );
439 }
440
441 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
442 {
443   mEventHandler->FeedWheelEvent( wheelEvent );
444 }
445
446 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
447 {
448   mEventHandler->FeedKeyEvent( keyEvent );
449 }
450
451 bool Adaptor::MoveResize( const PositionSize& positionSize )
452 {
453   PositionSize old = mSurface->GetPositionSize();
454
455   // just resize the surface. The driver should automatically resize the egl Surface (untested)
456   // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
457   // is resized. Implementations typically use hooks into the OS and native window
458   // system to perform this resizing on demand, transparently to the client.
459   mSurface->MoveResize( positionSize );
460
461   if(old.width != positionSize.width || old.height != positionSize.height)
462   {
463     SurfaceSizeChanged(positionSize);
464   }
465
466   return true;
467 }
468
469 void Adaptor::SurfaceResized( const PositionSize& positionSize )
470 {
471   PositionSize old = mSurface->GetPositionSize();
472
473   // Called by an application, when it has resized a window outside of Dali.
474   // The EGL driver automatically detects X Window resize calls, and resizes
475   // the EGL surface for us.
476   mSurface->MoveResize( positionSize );
477
478   if(old.width != positionSize.width || old.height != positionSize.height)
479   {
480     SurfaceSizeChanged(positionSize);
481   }
482 }
483
484 void Adaptor::ReplaceSurface( Dali::RenderSurface& surface )
485 {
486   // adaptor implementation needs the implementation of
487   RenderSurface* internalSurface = dynamic_cast<Internal::Adaptor::RenderSurface*>( &surface );
488   DALI_ASSERT_ALWAYS( internalSurface && "Incorrect surface" );
489
490   mSurface = internalSurface;
491
492   SurfaceSizeChanged( internalSurface->GetPositionSize() );
493
494   // flush the event queue to give update and render threads chance
495   // to start processing messages for new camera setup etc as soon as possible
496   ProcessCoreEvents();
497
498   // this method is synchronous
499   mUpdateRenderController->ReplaceSurface(internalSurface);
500 }
501
502 void Adaptor::RenderSync()
503 {
504   mUpdateRenderController->RenderSync();
505 }
506
507 Dali::RenderSurface& Adaptor::GetSurface() const
508 {
509   return *mSurface;
510 }
511
512 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
513 {
514   if(!mTtsPlayers[mode])
515   {
516     // Create the TTS player when it needed, because it can reduce launching time.
517     mTtsPlayers[mode] = TtsPlayer::New(mode);
518   }
519
520   return mTtsPlayers[mode];
521 }
522
523 bool Adaptor::AddIdle(boost::function<void(void)> callBack)
524 {
525   bool idleAdded(false);
526
527   // Only add an idle if the Adaptor is actually running
528   if( RUNNING == mState )
529   {
530     idleAdded = mCallbackManager->AddCallback(callBack, CallbackManager::IDLE_PRIORITY);
531   }
532
533   return idleAdded;
534 }
535
536 bool Adaptor::CallFromMainLoop(boost::function<void(void)> callBack)
537 {
538   bool callAdded(false);
539
540   // Only allow the callback if the Adaptor is actually running
541   if ( RUNNING == mState )
542   {
543     callAdded = mCallbackManager->AddCallback(callBack, CallbackManager::DEFAULT_PRIORITY);
544   }
545
546   return callAdded;
547 }
548
549 Dali::Adaptor& Adaptor::Get()
550 {
551   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() != NULL && "Adaptor not instantiated" );
552   return gThreadLocalAdaptor->mAdaptor;
553 }
554
555 bool Adaptor::IsAvailable()
556 {
557   return gThreadLocalAdaptor.get() != NULL;
558 }
559
560 Dali::Integration::Core& Adaptor::GetCore()
561 {
562   return *mCore;
563 }
564
565 void Adaptor::DisableVSync()
566 {
567   mUpdateRenderController->DisableVSync();
568 }
569
570 void Adaptor::SetDpi(size_t hDpi, size_t vDpi)
571 {
572   mHDpi = hDpi;
573   mVDpi = vDpi;
574 }
575
576 EglFactory& Adaptor::GetEGLFactory() const
577 {
578   DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
579   return *mEglFactory;
580 }
581
582 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
583 {
584   return *mEglFactory;
585 }
586
587 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
588 {
589   DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
590   return *mGLES;
591 }
592
593 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
594 {
595   return *mPlatformAbstraction;
596 }
597
598 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
599 {
600   return *mGLES;
601 }
602
603 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
604 {
605   return *mNotificationTrigger;
606 }
607 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
608 {
609   return mTriggerEventFactory;
610 }
611 RenderSurface* Adaptor::GetRenderSurfaceInterface()
612 {
613   return mSurface;
614 }
615 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
616 {
617   return mVSyncMonitor;
618 }
619
620 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
621 {
622   return mKernelTracer;
623 }
624
625 PerformanceInterface* Adaptor::GetPerformanceInterface()
626 {
627   return mPerformanceInterface;
628 }
629
630 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
631 {
632   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
633   return *mPlatformAbstraction;
634 }
635
636 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
637 {
638   mDragAndDropDetector = detector;
639
640   if ( mEventHandler )
641   {
642     mEventHandler->SetDragAndDropDetector( detector );
643   }
644 }
645
646 void Adaptor::SetRotationObserver( RotationObserver* observer )
647 {
648   if( mEventHandler )
649   {
650     mEventHandler->SetRotationObserver( observer );
651   }
652   else if( mState == READY )
653   {
654     // Set once event handler exists
655     mDeferredRotationObserver = observer;
656   }
657 }
658
659 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
660 {
661   if(mTtsPlayers[mode])
662   {
663     mTtsPlayers[mode].Reset();
664   }
665 }
666
667 void Adaptor::SetMinimumPinchDistance(float distance)
668 {
669   if( mGestureManager )
670   {
671     mGestureManager->SetMinimumPinchDistance(distance);
672   }
673 }
674
675 void Adaptor::AddObserver( LifeCycleObserver& observer )
676 {
677   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
678
679   if ( match == mObservers.end() )
680   {
681     mObservers.push_back( &observer );
682   }
683 }
684
685 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
686 {
687   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
688
689   if ( match != mObservers.end() )
690   {
691     mObservers.erase( match );
692   }
693 }
694
695 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
696 {
697   if( mCore )
698   {
699     mCore->QueueEvent(event);
700   }
701 }
702
703 void Adaptor::ProcessCoreEvents()
704 {
705   if( mCore )
706   {
707     if( mPerformanceInterface )
708     {
709       mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_START );
710     }
711
712     mCore->ProcessEvents();
713
714     if( mPerformanceInterface )
715     {
716       mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_END );
717     }
718   }
719 }
720
721 void Adaptor::RequestUpdate()
722 {
723   // When Dali applications are partially visible behind the lock-screen,
724   // the indicator must be updated (therefore allow updates in the PAUSED state)
725   if ( PAUSED  == mState ||
726        RUNNING == mState )
727   {
728     mUpdateRenderController->RequestUpdate();
729   }
730 }
731
732 void Adaptor::RequestProcessEventsOnIdle()
733 {
734   // Only request a notification if the Adaptor is actually running
735   if ( RUNNING == mState )
736   {
737     boost::unique_lock<boost::mutex> lock( mIdleInstaller );
738
739     // check if the idle handle is already installed
740     if( mNotificationOnIdleInstalled )
741     {
742       return;
743     }
744     mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
745   }
746 }
747
748 void Adaptor::OnWindowShown()
749 {
750   if ( PAUSED_WHILE_HIDDEN == mState )
751   {
752     // Adaptor can now be resumed
753     mState = PAUSED;
754
755     Resume();
756
757     // Force a render task
758     RequestUpdateOnce();
759   }
760 }
761
762 void Adaptor::OnWindowHidden()
763 {
764   if ( STOPPED != mState )
765   {
766     Pause();
767
768     // Adaptor cannot be resumed until the window is shown
769     mState = PAUSED_WHILE_HIDDEN;
770   }
771 }
772
773 // Dali::Internal::Adaptor::Adaptor::OnDamaged
774 void Adaptor::OnDamaged( const DamageArea& area )
775 {
776   // This is needed for the case where Dali window is partially obscured
777   RequestUpdate();
778 }
779
780 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
781 {
782   // let the core know the surface size has changed
783   mCore->SurfaceResized(positionSize.width, positionSize.height);
784
785   mResizedSignalV2.Emit( mAdaptor );
786 }
787
788 void Adaptor::NotifyLanguageChanged()
789 {
790   mLanguageChangedSignalV2.Emit( mAdaptor );
791 }
792
793 void Adaptor::RequestUpdateOnce()
794 {
795   if( PAUSED_WHILE_HIDDEN != mState )
796   {
797     if( mUpdateRenderController )
798     {
799       mUpdateRenderController->RequestUpdateOnce();
800     }
801   }
802 }
803
804 void Adaptor::ProcessCoreEventsFromIdle()
805 {
806   ProcessCoreEvents();
807
808   // the idle handle automatically un-installs itself
809   mNotificationOnIdleInstalled = false;
810 }
811
812 void Adaptor::RegisterSingleton(const std::type_info& info, BaseHandle singleton)
813 {
814   if(singleton)
815   {
816     mSingletonContainer.insert(SingletonPair(info.name(), singleton));
817   }
818 }
819
820 BaseHandle Adaptor::GetSingleton(const std::type_info& info) const
821 {
822   BaseHandle object = Dali::BaseHandle();
823
824   SingletonConstIter iter = mSingletonContainer.find(info.name());
825   if(iter != mSingletonContainer.end())
826   {
827     object = (*iter).second;
828   }
829
830   return object;
831 }
832
833 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
834 : mAdaptor(adaptor),
835   mState(READY),
836   mCore(NULL),
837   mUpdateRenderController(NULL),
838   mVSyncMonitor(NULL),
839   mGLES( NULL ),
840   mEglFactory( NULL ),
841   mSurface( surface ),
842   mPlatformAbstraction( NULL ),
843   mEventHandler( NULL ),
844   mCallbackManager( NULL ),
845   mNotificationOnIdleInstalled( false ),
846   mNotificationTrigger(NULL),
847   mGestureManager(NULL),
848   mHDpi( 0 ),
849   mVDpi( 0 ),
850   mDaliFeedbackPlugin(NULL),
851   mFeedbackController(NULL),
852   mObservers(),
853   mDragAndDropDetector(),
854   mDeferredRotationObserver(NULL),
855   mBaseLayout(baseLayout),
856   mEnvironmentOptions(),
857   mPerformanceInterface(NULL),
858   mObjectProfiler(NULL)
859 {
860   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
861   gThreadLocalAdaptor.reset(this);
862 }
863
864 // Stereoscopy
865
866 void Adaptor::SetViewMode( ViewMode viewMode )
867 {
868   mSurface->SetViewMode( viewMode );
869   mCore->SetViewMode( viewMode );
870 }
871
872 ViewMode Adaptor::GetViewMode() const
873 {
874   return mCore->GetViewMode();
875 }
876
877 void Adaptor::SetStereoBase( float stereoBase )
878 {
879   mCore->SetStereoBase( stereoBase );
880 }
881
882 float Adaptor::GetStereoBase() const
883 {
884   return mCore->GetStereoBase();
885 }
886
887 } // namespace Adaptor
888
889 } // namespace Internal
890
891 } // namespace Dali