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