Merge branch 'devel/master' into tizen
[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/system/common/command-line-options.h>
28 #include <dali/internal/adaptor/common/framework.h>
29 #include <dali/internal/system/common/singleton-service-impl.h>
30 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
31 #include <dali/internal/window-system/common/window-impl.h>
32 #include <dali/internal/window-system/common/window-render-surface.h>
33 #include <dali/internal/window-system/common/render-surface-factory.h>
34
35 // To disable a macro with the same name from one of OpenGL headers
36 #undef Status
37
38 namespace Dali
39 {
40
41 namespace TizenPlatform
42 {
43 class TizenPlatformAbstraction;
44 }
45
46 namespace Integration
47 {
48 class Core;
49 }
50
51 namespace Internal
52 {
53
54 namespace Adaptor
55 {
56
57 namespace
58 {
59
60 const float DEFAULT_STEREO_BASE( 65.0f );
61
62 } // unnamed namespace
63
64 ApplicationPtr Application::gPreInitializedApplication( NULL );
65
66 ApplicationPtr Application::New(
67   int* argc,
68   char **argv[],
69   const std::string& stylesheet,
70   Dali::Application::WINDOW_MODE windowMode,
71   const PositionSize& positionSize,
72   Framework::Type applicationType)
73 {
74   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
75   return application;
76 }
77
78 void Application::PreInitialize( int* argc, char** argv[] )
79 {
80   if( !gPreInitializedApplication )
81   {
82     gPreInitializedApplication = new Application ( argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL );
83
84     gPreInitializedApplication->CreateWindow();    // Only create window
85
86     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
87
88     //Make DefaultFontDescription cached
89     Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
90     Dali::TextAbstraction::FontDescription defaultFontDescription;
91     fontClient.GetDefaultPlatformFontDescription( defaultFontDescription );
92   }
93 }
94
95 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
96   Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType )
97 : mInitSignal(),
98   mTerminateSignal(),
99   mPauseSignal(),
100   mResumeSignal(),
101   mResetSignal(),
102   mResizeSignal(),
103   mAppControlSignal(),
104   mLanguageChangedSignal(),
105   mRegionChangedSignal(),
106   mBatteryLowSignal(),
107   mMemoryLowSignal(),
108   mEventLoop( nullptr ),
109   mFramework( nullptr ),
110   mContextLossConfiguration( Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS ),
111   mCommandLineOptions( nullptr ),
112   mSingletonService( SingletonService::New() ),
113   mAdaptorBuilder( nullptr ),
114   mAdaptor( nullptr ),
115   mMainWindow(),
116   mMainWindowMode( windowMode ),
117   mMainWindowName(),
118   mMainWindowReplaced( false ),
119   mStylesheet( stylesheet ),
120   mEnvironmentOptions(),
121   mWindowPositionSize( positionSize ),
122   mLaunchpadState( Launchpad::NONE ),
123   mSlotDelegate( this ),
124   mViewMode( MONO ),
125   mStereoBase( DEFAULT_STEREO_BASE )
126 {
127   // Get mName from environment options
128   mMainWindowName = mEnvironmentOptions.GetWindowName();
129   if( mMainWindowName.empty() && argc && ( *argc > 0 ) )
130   {
131     // Set mName from command-line args if environment option not set
132     mMainWindowName = (*argv)[0];
133   }
134
135   mCommandLineOptions = new CommandLineOptions(argc, argv);
136   mFramework = new Framework( *this, argc, argv, applicationType );
137   mUseRemoteSurface = (applicationType == Framework::WATCH);
138 }
139
140 Application::~Application()
141 {
142   mSingletonService.UnregisterAll();
143
144   mMainWindow.Reset();
145   delete mAdaptor;
146   delete mAdaptorBuilder;
147   delete mCommandLineOptions;
148   delete mFramework;
149 }
150
151 void Application::CreateWindow()
152 {
153   if( mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0 )
154   {
155     if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
156     {
157       // Command line options override environment options and full screen
158       mWindowPositionSize.width = mCommandLineOptions->stageWidth;
159       mWindowPositionSize.height = mCommandLineOptions->stageHeight;
160     }
161     else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
162     {
163       // Environment options override full screen functionality if command line arguments not provided
164       mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
165       mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
166     }
167   }
168
169   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
170   mMainWindow = Dali::Window::New( mWindowPositionSize, mMainWindowName, windowClassName, mMainWindowMode == Dali::Application::TRANSPARENT );
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   mAdaptor = Dali::Internal::Adaptor::Adaptor::New( graphicsFactory, mMainWindow, mContextLossConfiguration, &mEnvironmentOptions );
183
184   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
185
186   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
187 }
188
189 void Application::CreateAdaptorBuilder()
190 {
191   mAdaptorBuilder = new AdaptorBuilder();
192 }
193
194 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
195 {
196   mContextLossConfiguration = configuration;
197
198   // Run the application
199   mFramework->Run();
200 }
201
202 void Application::Lower()
203 {
204   // Lower the application without quitting it.
205   mMainWindow.Lower();
206 }
207
208 void Application::Quit()
209 {
210   // Actually quit the application.
211   // Force a call to Quit even if adaptor is not running.
212   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ), false, true );
213 }
214
215 void Application::QuitFromMainLoop()
216 {
217   mAdaptor->Stop();
218
219   mFramework->Quit();
220   // This will trigger OnTerminate(), below, after the main loop has completed.
221 }
222
223 void Application::OnInit()
224 {
225   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
226
227   CreateAdaptorBuilder();
228
229   // If an application was pre-initialized, a window was made in advance
230   if( mLaunchpadState == Launchpad::NONE )
231   {
232     CreateWindow();
233   }
234
235   CreateAdaptor();
236
237   // Run the adaptor
238   mAdaptor->Start();
239
240   // Check if user requires no vsyncing and set Adaptor
241   if (mCommandLineOptions->noVSyncOnRender)
242   {
243     mAdaptor->SetUseHardwareVSync(false);
244   }
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::OnResize(Dali::Adaptor& adaptor)
355 {
356   Dali::Application application(this);
357   mResizeSignal.Emit( application );
358 }
359
360 bool Application::AddIdle( CallbackBase* callback, bool hasReturnValue )
361 {
362   return mAdaptor->AddIdle( callback, hasReturnValue );
363 }
364
365 std::string Application::GetRegion() const
366 {
367   return mFramework->GetRegion();
368 }
369
370 std::string Application::GetLanguage() const
371 {
372   return mFramework->GetLanguage();
373 }
374
375 Dali::Adaptor& Application::GetAdaptor()
376 {
377   return *mAdaptor;
378 }
379
380 Dali::Window Application::GetWindow()
381 {
382   // Changed to return a different window handle after ReplaceWindow is called
383   // just for backward compatibility to make the test case pass
384   return mMainWindowReplaced ? Dali::Window::New( PositionSize(), "ReplacedWindow" ) : mMainWindow;
385 }
386
387 // Stereoscopy
388
389 void Application::SetViewMode( ViewMode viewMode )
390 {
391   mViewMode = viewMode;
392 }
393
394 ViewMode Application::GetViewMode() const
395 {
396   return mViewMode;
397 }
398
399 void Application::SetStereoBase( float stereoBase )
400 {
401   mStereoBase = stereoBase;
402 }
403
404 float Application::GetStereoBase() const
405 {
406   return mStereoBase;
407 }
408
409 void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
410 {
411   // This API is kept just for backward compatibility to make the test case pass.
412
413   mMainWindowReplaced = true;
414   OnResize( *mAdaptor );
415 }
416
417 std::string Application::GetResourcePath()
418 {
419   return Internal::Adaptor::Framework::GetResourcePath();
420 }
421
422 std::string Application::GetDataPath()
423 {
424   return Internal::Adaptor::Framework::GetDataPath();
425 }
426
427 void Application::SetStyleSheet( const std::string& stylesheet )
428 {
429   mStylesheet = stylesheet;
430 }
431
432 ApplicationPtr Application::GetPreInitializedApplication()
433 {
434   return gPreInitializedApplication;
435 }
436
437 } // namespace Adaptor
438
439 } // namespace Internal
440
441 } // namespace Dali