Merge "Moved SingletonService into dali-core" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / application-impl.cpp
1 /*
2  * Copyright (c) 2018 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/application-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/devel-api/common/singleton-service.h>
24
25 // INTERNAL INCLUDES
26 #include <dali/devel-api/adaptor-framework/style-monitor.h>
27 #include <dali/devel-api/text-abstraction/font-client.h>
28 #include <dali/internal/adaptor/common/adaptor-impl.h>
29 #include <dali/internal/system/common/command-line-options.h>
30 #include <dali/internal/adaptor/common/framework.h>
31 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
32 #include <dali/internal/window-system/common/window-impl.h>
33 #include <dali/internal/window-system/common/window-render-surface.h>
34 #include <dali/internal/window-system/common/render-surface-factory.h>
35
36 // To disable a macro with the same name from one of OpenGL headers
37 #undef Status
38
39 namespace Dali
40 {
41
42 namespace TizenPlatform
43 {
44 class TizenPlatformAbstraction;
45 }
46
47 namespace Integration
48 {
49 class Core;
50 }
51
52 namespace Internal
53 {
54
55 namespace Adaptor
56 {
57
58 namespace
59 {
60
61 const float DEFAULT_STEREO_BASE( 65.0f );
62
63 } // unnamed namespace
64
65 ApplicationPtr Application::gPreInitializedApplication( NULL );
66
67 ApplicationPtr Application::New(
68   int* argc,
69   char **argv[],
70   const std::string& stylesheet,
71   Dali::Application::WINDOW_MODE windowMode,
72   const PositionSize& positionSize,
73   Framework::Type applicationType)
74 {
75   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
76   return application;
77 }
78
79 void Application::PreInitialize( int* argc, char** argv[] )
80 {
81   if( !gPreInitializedApplication )
82   {
83     gPreInitializedApplication = new Application ( argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL );
84     gPreInitializedApplication->CreateWindow();    // Only create window
85     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
86
87     //Make DefaultFontDescription cached
88     Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
89     Dali::TextAbstraction::FontDescription defaultFontDescription;
90     fontClient.GetDefaultPlatformFontDescription( defaultFontDescription );
91   }
92 }
93
94 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
95   Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType )
96 : mInitSignal(),
97   mTerminateSignal(),
98   mPauseSignal(),
99   mResumeSignal(),
100   mResetSignal(),
101   mResizeSignal(),
102   mAppControlSignal(),
103   mLanguageChangedSignal(),
104   mRegionChangedSignal(),
105   mBatteryLowSignal(),
106   mMemoryLowSignal(),
107   mEventLoop( nullptr ),
108   mFramework( nullptr ),
109   mContextLossConfiguration( Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS ),
110   mCommandLineOptions( nullptr ),
111   mAdaptorBuilder( nullptr ),
112   mAdaptor( nullptr ),
113   mMainWindow(),
114   mMainWindowMode( windowMode ),
115   mMainWindowName(),
116   mMainWindowReplaced( false ),
117   mStylesheet( stylesheet ),
118   mEnvironmentOptions(),
119   mWindowPositionSize( positionSize ),
120   mLaunchpadState( Launchpad::NONE ),
121   mSlotDelegate( this ),
122   mViewMode( MONO ),
123   mStereoBase( DEFAULT_STEREO_BASE )
124 {
125   // Get mName from environment options
126   mMainWindowName = mEnvironmentOptions.GetWindowName();
127   if( mMainWindowName.empty() && argc && ( *argc > 0 ) )
128   {
129     // Set mName from command-line args if environment option not set
130     mMainWindowName = (*argv)[0];
131   }
132
133   mCommandLineOptions = new CommandLineOptions(argc, argv);
134   mFramework = new Framework( *this, argc, argv, applicationType );
135   mUseRemoteSurface = (applicationType == Framework::WATCH);
136 }
137
138 Application::~Application()
139 {
140   SingletonService service = SingletonService::Get();
141   // Note this can be false i.e. if Application has never created a Core instance
142   if( service )
143   {
144     service.UnregisterAll();
145   }
146
147   mMainWindow.Reset();
148   delete mAdaptor;
149   delete mAdaptorBuilder;
150   delete mCommandLineOptions;
151   delete mFramework;
152 }
153
154 void Application::CreateWindow()
155 {
156   if( mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0 )
157   {
158     if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
159     {
160       // Command line options override environment options and full screen
161       mWindowPositionSize.width = mCommandLineOptions->stageWidth;
162       mWindowPositionSize.height = mCommandLineOptions->stageHeight;
163     }
164     else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
165     {
166       // Environment options override full screen functionality if command line arguments not provided
167       mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
168       mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
169     }
170   }
171
172   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
173
174   Internal::Adaptor::Window* window = Internal::Adaptor::Window::New( mWindowPositionSize, mMainWindowName, windowClassName, mMainWindowMode == Dali::Application::TRANSPARENT );
175   mMainWindow = Dali::Window( window );
176
177   // Quit the application when the window is closed
178   GetImplementation( mMainWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
179 }
180
181 void Application::CreateAdaptor()
182 {
183   DALI_ASSERT_ALWAYS( mMainWindow && "Window required to create adaptor" );
184
185   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
186
187   Integration::SceneHolder sceneHolder = Integration::SceneHolder( &Dali::GetImplementation( mMainWindow ) );
188
189   mAdaptor = Adaptor::New( graphicsFactory, sceneHolder, mContextLossConfiguration, &mEnvironmentOptions );
190
191   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
192
193   Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
194 }
195
196 void Application::CreateAdaptorBuilder()
197 {
198   mAdaptorBuilder = new AdaptorBuilder();
199 }
200
201 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
202 {
203   mContextLossConfiguration = configuration;
204
205   // Run the application
206   mFramework->Run();
207 }
208
209 void Application::Lower()
210 {
211   // Lower the application without quitting it.
212   mMainWindow.Lower();
213 }
214
215 void Application::Quit()
216 {
217   // Actually quit the application.
218   // Force a call to Quit even if adaptor is not running.
219   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ), false, true );
220 }
221
222 void Application::QuitFromMainLoop()
223 {
224   mAdaptor->Stop();
225
226   mFramework->Quit();
227   // This will trigger OnTerminate(), below, after the main loop has completed.
228 }
229
230 void Application::OnInit()
231 {
232   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
233
234   CreateAdaptorBuilder();
235   // If an application was pre-initialized, a window was made in advance
236   if( mLaunchpadState == Launchpad::NONE )
237   {
238     CreateWindow();
239   }
240
241   CreateAdaptor();
242
243   // Run the adaptor
244   mAdaptor->Start();
245
246   if( ! mStylesheet.empty() )
247   {
248     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
249   }
250
251   // Wire up the LifecycleController
252   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
253
254   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
255   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
256   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
257   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
258   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
259   ResizeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResize );
260   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
261
262   Dali::Application application(this);
263   mInitSignal.Emit( application );
264
265   mAdaptor->NotifySceneCreated();
266 }
267
268 void Application::OnTerminate()
269 {
270   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
271   // delete the window as ecore_x has been destroyed by AppCore
272
273   Dali::Application application(this);
274   mTerminateSignal.Emit( application );
275
276   if( mAdaptor )
277   {
278     // Ensure that the render-thread is not using the surface(window) after we delete it
279     mAdaptor->Stop();
280   }
281
282   mMainWindow.Reset(); // This only resets (clears) the default Window
283 }
284
285 void Application::OnPause()
286 {
287   // A DALi app should handle Pause/Resume events.
288   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
289   // Pausing DALi core only occurs on the Window Hidden framework event
290   Dali::Application application(this);
291   mPauseSignal.Emit( application );
292 }
293
294 void Application::OnResume()
295 {
296   // Emit the signal first so the application can queue any messages before we do an update/render
297   // This ensures we do not just redraw the last frame before pausing if that's not required
298   Dali::Application application(this);
299   mResumeSignal.Emit( application );
300
301   // DALi just delivers the framework Resume event to the application.
302   // Resuming DALi core only occurs on the Window Show framework event
303
304   // Trigger processing of events queued up while paused
305   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation( GetAdaptor() );
306   coreEventInterface.ProcessCoreEvents();
307 }
308
309 void Application::OnReset()
310 {
311   /*
312    * usually, reset callback was called when a caller request to launch this application via aul.
313    * because Application class already handled initialization in OnInit(), OnReset do nothing.
314    */
315   Dali::Application application(this);
316   mResetSignal.Emit( application );
317 }
318
319 void Application::OnAppControl(void *data)
320 {
321   Dali::Application application(this);
322   mAppControlSignal.Emit( application , data );
323 }
324
325 void Application::OnLanguageChanged()
326 {
327   mAdaptor->NotifyLanguageChanged();
328   Dali::Application application(this);
329   mLanguageChangedSignal.Emit( application );
330 }
331
332 void Application::OnRegionChanged()
333 {
334   Dali::Application application(this);
335   mRegionChangedSignal.Emit( application );
336 }
337
338 void Application::OnBatteryLow( Dali::DeviceStatus::Battery::Status status )
339 {
340   Dali::Application application(this);
341   mBatteryLowSignal.Emit( application );
342
343   mLowBatterySignal.Emit( status );
344 }
345
346 void Application::OnMemoryLow( Dali::DeviceStatus::Memory::Status status )
347 {
348   Dali::Application application(this);
349   mMemoryLowSignal.Emit( application );
350
351   mLowMemorySignal.Emit( status );
352 }
353
354 void Application::OnSurfaceCreated( Any newSurface )
355 {
356   void* newWindow = AnyCast< void* >( newSurface );
357   void* oldWindow = AnyCast< void* >( mMainWindow.GetNativeHandle() );
358   if( oldWindow != newWindow )
359   {
360     auto renderSurfaceFactory = Dali::Internal::Adaptor::GetRenderSurfaceFactory();
361     std::unique_ptr< WindowRenderSurface > newSurfacePtr
362       = renderSurfaceFactory->CreateWindowRenderSurface( PositionSize(), newSurface, true );
363
364     mAdaptor->ReplaceSurface( mMainWindow, *newSurfacePtr.release() );
365   }
366 }
367
368 void Application::OnSurfaceDestroyed( Any surface )
369 {
370   void* windowToDelete = AnyCast< void* >( surface );
371   void* oldWindow = AnyCast< void* >( mMainWindow.GetNativeHandle() );
372   if( oldWindow == windowToDelete )
373   {
374     mAdaptor->DeleteSurface( mAdaptor->GetSurface() );
375   }
376 }
377
378 void Application::OnResize(Dali::Adaptor& adaptor)
379 {
380   Dali::Application application(this);
381   mResizeSignal.Emit( application );
382 }
383
384 bool Application::AddIdle( CallbackBase* callback, bool hasReturnValue )
385 {
386   return mAdaptor->AddIdle( callback, hasReturnValue );
387 }
388
389 std::string Application::GetRegion() const
390 {
391   return mFramework->GetRegion();
392 }
393
394 std::string Application::GetLanguage() const
395 {
396   return mFramework->GetLanguage();
397 }
398
399 Dali::Adaptor& Application::GetAdaptor()
400 {
401   return *mAdaptor;
402 }
403
404 Dali::Window Application::GetWindow()
405 {
406   // Changed to return a different window handle after ReplaceWindow is called
407   // just for backward compatibility to make the test case pass
408   if ( mMainWindowReplaced )
409   {
410     Internal::Adaptor::Window* window = Internal::Adaptor::Window::New( PositionSize(), "ReplacedWindow", "", false );
411     return Dali::Window( window );
412   }
413   else
414   {
415     return mMainWindow;
416   }
417 }
418
419 // Stereoscopy
420
421 void Application::SetViewMode( ViewMode viewMode )
422 {
423   mViewMode = viewMode;
424 }
425
426 ViewMode Application::GetViewMode() const
427 {
428   return mViewMode;
429 }
430
431 void Application::SetStereoBase( float stereoBase )
432 {
433   mStereoBase = stereoBase;
434 }
435
436 float Application::GetStereoBase() const
437 {
438   return mStereoBase;
439 }
440
441 void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
442 {
443   // This API is kept just for backward compatibility to make the test case pass.
444
445   mMainWindowReplaced = true;
446   OnResize( *mAdaptor );
447 }
448
449 std::string Application::GetResourcePath()
450 {
451   return Internal::Adaptor::Framework::GetResourcePath();
452 }
453
454 std::string Application::GetDataPath()
455 {
456   return Internal::Adaptor::Framework::GetDataPath();
457 }
458
459 void Application::SetStyleSheet( const std::string& stylesheet )
460 {
461   mStylesheet = stylesheet;
462 }
463
464 void Application::SetCommandLineOptions( int* argc, char **argv[] )
465 {
466   delete mCommandLineOptions;
467
468   mCommandLineOptions = new CommandLineOptions( argc, argv );
469
470   mFramework->SetCommandLineOptions( argc, argv );
471 }
472
473 ApplicationPtr Application::GetPreInitializedApplication()
474 {
475   return gPreInitializedApplication;
476 }
477
478 } // namespace Adaptor
479
480 } // namespace Internal
481
482 } // namespace Dali