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