Merge "DALi Version 1.2.50" into devel/master
[platform/core/uifw/dali-adaptor.git] / adaptors / common / application-impl.cpp
1 /*
2  * Copyright (c) 2017 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 "application-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <style-monitor.h>
26 #include <command-line-options.h>
27 #include <common/adaptor-impl.h>
28 #include <common/framework.h>
29 #include <singleton-service-impl.h>
30 #include <lifecycle-controller-impl.h>
31
32 namespace Dali
33 {
34
35 namespace TizenPlatform
36 {
37 class TizenPlatformAbstraction;
38 }
39
40 namespace Integration
41 {
42 class Core;
43 }
44
45 namespace Internal
46 {
47
48 namespace Adaptor
49 {
50
51 ApplicationPtr Application::gPreInitializedApplication( NULL );
52
53 ApplicationPtr Application::New(
54   int* argc,
55   char **argv[],
56   const std::string& stylesheet,
57   Dali::Application::WINDOW_MODE windowMode,
58   const PositionSize& positionSize,
59   Framework::Type applicationType)
60 {
61   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
62   return application;
63 }
64
65 void Application::PreInitialize( int* argc, char** argv[] )
66 {
67   if( !gPreInitializedApplication )
68   {
69     gPreInitializedApplication = new Application ( argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL );
70
71     gPreInitializedApplication->CreateWindow();    // Only create window
72   }
73 }
74
75 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
76   Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType )
77 : mInitSignal(),
78   mTerminateSignal(),
79   mPauseSignal(),
80   mResumeSignal(),
81   mResetSignal(),
82   mResizeSignal(),
83   mAppControlSignal(),
84   mLanguageChangedSignal(),
85   mRegionChangedSignal(),
86   mBatteryLowSignal(),
87   mMemoryLowSignal(),
88   mEventLoop( NULL ),
89   mFramework( NULL ),
90   mContextLossConfiguration( Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS ),
91   mCommandLineOptions( NULL ),
92   mSingletonService( SingletonService::New() ),
93   mAdaptor( NULL ),
94   mWindow(),
95   mWindowMode( windowMode ),
96   mName(),
97   mStylesheet( stylesheet ),
98   mEnvironmentOptions(),
99   mWindowPositionSize( positionSize ),
100   mLaunchpadState( Launchpad::NONE ),
101   mSlotDelegate( this )
102 {
103   // Get mName from environment options
104   mName = mEnvironmentOptions.GetWindowName();
105   if( mName.empty() && argc && ( *argc > 0 ) )
106   {
107     // Set mName from command-line args if environment option not set
108     mName = (*argv)[0];
109   }
110
111   mCommandLineOptions = new CommandLineOptions(argc, argv);
112   mFramework = new Framework( *this, argc, argv, applicationType );
113   mUseRemoteSurface = (applicationType == Framework::WATCH);
114 }
115
116 Application::~Application()
117 {
118   mSingletonService.UnregisterAll();
119
120   mWindow.Reset();
121   delete mAdaptor;
122   delete mCommandLineOptions;
123   delete mFramework;
124 }
125
126 void Application::CreateWindow()
127 {
128   if( mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0 )
129   {
130     if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
131     {
132       // Command line options override environment options and full screen
133       mWindowPositionSize.width = mCommandLineOptions->stageWidth;
134       mWindowPositionSize.height = mCommandLineOptions->stageHeight;
135     }
136     else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
137     {
138       // Environment options override full screen functionality if command line arguments not provided
139       mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
140       mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
141     }
142   }
143
144   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
145   mWindow = Dali::Window::New( mWindowPositionSize, mName, windowClassName, mWindowMode == Dali::Application::TRANSPARENT );
146
147   // Quit the application when the window is closed
148   GetImplementation( mWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
149 }
150
151 void Application::CreateAdaptor()
152 {
153   DALI_ASSERT_ALWAYS( mWindow && "Window required to create adaptor" );
154
155   mAdaptor = Dali::Internal::Adaptor::Adaptor::New( mWindow, mContextLossConfiguration, &mEnvironmentOptions );
156
157   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
158
159   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
160 }
161
162 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
163 {
164   mContextLossConfiguration = configuration;
165
166   // Run the application
167   mFramework->Run();
168 }
169
170 void Application::Lower()
171 {
172   // Lower the application without quitting it.
173   mWindow.Lower();
174 }
175
176 void Application::Quit()
177 {
178   // Actually quit the application.
179   AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ) );
180 }
181
182 void Application::QuitFromMainLoop()
183 {
184   mAdaptor->Stop();
185
186   mFramework->Quit();
187   // This will trigger OnTerminate(), below, after the main loop has completed.
188 }
189
190 void Application::DoInit()
191 {
192   // If an application was pre-initialized, a window was made in advance
193   if( mLaunchpadState == Launchpad::NONE )
194   {
195     CreateWindow();
196   }
197
198   CreateAdaptor();
199
200   // Run the adaptor
201   mAdaptor->Start();
202
203   // Check if user requires no vsyncing and set Adaptor
204   if (mCommandLineOptions->noVSyncOnRender)
205   {
206     mAdaptor->SetUseHardwareVSync(false);
207   }
208
209   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetStereoBase( mCommandLineOptions->stereoBase );
210   if( mCommandLineOptions->viewMode != 0 )
211   {
212     ViewMode viewMode = MONO;
213     if( mCommandLineOptions->viewMode <= STEREO_INTERLACED )
214     {
215       viewMode = static_cast<ViewMode>( mCommandLineOptions->viewMode );
216     }
217     Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetViewMode( viewMode );
218   }
219
220   if( ! mStylesheet.empty() )
221   {
222     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
223   }
224 }
225
226 void Application::DoStart()
227 {
228   mAdaptor->NotifySceneCreated();
229 }
230
231 void Application::DoTerminate()
232 {
233   if( mAdaptor )
234   {
235     // Ensure that the render-thread is not using the surface(window) after we delete it
236     mAdaptor->Stop();
237   }
238
239   mWindow.Reset();
240 }
241
242 void Application::DoPause()
243 {
244   mAdaptor->Pause();
245 }
246
247 void Application::DoResume()
248 {
249   mAdaptor->Resume();
250 }
251
252 void Application::DoLanguageChange()
253 {
254   mAdaptor->NotifyLanguageChanged();
255 }
256
257 void Application::OnInit()
258 {
259   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
260
261   DoInit();
262
263   // Wire up the LifecycleController
264   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
265
266   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
267   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
268   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
269   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
270   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
271   ResizeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResize );
272   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
273
274   Dali::Application application(this);
275   mInitSignal.Emit( application );
276
277   DoStart();
278 }
279
280 void Application::OnTerminate()
281 {
282   // we've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
283   // delete the window as ecore_x has been destroyed by AppCore
284
285   Dali::Application application(this);
286   mTerminateSignal.Emit( application );
287
288   DoTerminate();
289 }
290
291 void Application::OnPause()
292 {
293   // A DALi app should handle Pause/Resume events.
294   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
295   // Pausing DALi core only occurs on the Window Hidden framework event
296   Dali::Application application(this);
297   mPauseSignal.Emit( application );
298 }
299
300 void Application::OnResume()
301 {
302   // Emit the signal first so the application can queue any messages before we do an update/render
303   // This ensures we do not just redraw the last frame before pausing if that's not required
304   Dali::Application application(this);
305   mResumeSignal.Emit( application );
306
307   // DALi just delivers the framework Resume event to the application.
308   // Resuming DALi core only occurs on the Window Show framework event
309 }
310
311 void Application::OnReset()
312 {
313   /*
314    * usually, reset callback was called when a caller request to launch this application via aul.
315    * because Application class already handled initialization in OnInit(), OnReset do nothing.
316    */
317   Dali::Application application(this);
318   mResetSignal.Emit( application );
319 }
320
321 void Application::OnAppControl(void *data)
322 {
323   Dali::Application application(this);
324   mAppControlSignal.Emit( application , data );
325 }
326
327 void Application::OnLanguageChanged()
328 {
329   DoLanguageChange();
330   Dali::Application application(this);
331   mLanguageChangedSignal.Emit( application );
332 }
333
334 void Application::OnRegionChanged()
335 {
336   Dali::Application application(this);
337   mRegionChangedSignal.Emit( application );
338 }
339
340 void Application::OnBatteryLow()
341 {
342   Dali::Application application(this);
343   mBatteryLowSignal.Emit( application );
344 }
345
346 void Application::OnMemoryLow()
347 {
348   Dali::Application application(this);
349   mMemoryLowSignal.Emit( application );
350 }
351
352 void Application::OnResize(Dali::Adaptor& adaptor)
353 {
354   Dali::Application application(this);
355   mResizeSignal.Emit( application );
356 }
357
358 bool Application::AddIdle( CallbackBase* callback )
359 {
360   return mAdaptor->AddIdle( callback );
361 }
362
363 Dali::Adaptor& Application::GetAdaptor()
364 {
365   return *mAdaptor;
366 }
367
368 Dali::Window Application::GetWindow()
369 {
370   return mWindow;
371 }
372
373 // Stereoscopy
374
375 void Application::SetViewMode( ViewMode viewMode )
376 {
377   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetViewMode( viewMode );
378 }
379
380 ViewMode Application::GetViewMode() const
381 {
382   return Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).GetViewMode();
383 }
384
385 void Application::SetStereoBase( float stereoBase )
386 {
387   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetStereoBase( stereoBase );
388 }
389
390 float Application::GetStereoBase() const
391 {
392   return Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).GetStereoBase();
393 }
394
395
396 void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
397 {
398   Dali::Window newWindow = Dali::Window::New( positionSize, name, mWindowMode == Dali::Application::TRANSPARENT );
399   Window& windowImpl = GetImplementation(newWindow);
400   windowImpl.SetAdaptor(*mAdaptor);
401   newWindow.ShowIndicator(Dali::Window::INVISIBLE);
402   Dali::RenderSurface* renderSurface = windowImpl.GetSurface();
403
404   Any nativeWindow = newWindow.GetNativeHandle();
405   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).ReplaceSurface(nativeWindow, *renderSurface);
406   mWindow = newWindow;
407   mWindowPositionSize = positionSize;
408 }
409
410 std::string Application::GetResourcePath()
411 {
412   return Internal::Adaptor::Framework::GetResourcePath();
413 }
414
415 void Application::SetStyleSheet( const std::string& stylesheet )
416 {
417   mStylesheet = stylesheet;
418 }
419
420
421 ApplicationPtr Application::GetPreInitializedApplication()
422 {
423   return gPreInitializedApplication;
424 }
425
426 } // namespace Adaptor
427
428 } // namespace Internal
429
430 } // namespace Dali