0cf22281a1893836347f01f8dcf333d724891323
[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/internal/system/common/command-line-options.h>
27 #include <dali/internal/adaptor/common/framework.h>
28 #include <dali/internal/system/common/singleton-service-impl.h>
29 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
30 #include <dali/internal/window-system/common/window-impl.h>
31 #include <dali/internal/window-system/common/window-render-surface.h>
32 #include <dali/internal/window-system/common/render-surface-factory.h>
33
34 // To disable a macro with the same name from one of OpenGL headers
35 #undef Status
36
37 namespace Dali
38 {
39
40 namespace TizenPlatform
41 {
42 class TizenPlatformAbstraction;
43 }
44
45 namespace Integration
46 {
47 class Core;
48 }
49
50 namespace Internal
51 {
52
53 namespace Adaptor
54 {
55
56 namespace
57 {
58
59 const float DEFAULT_STEREO_BASE( 65.0f );
60
61 } // unnamed namespace
62
63 ApplicationPtr Application::gPreInitializedApplication( NULL );
64
65 ApplicationPtr Application::New(
66   int* argc,
67   char **argv[],
68   const std::string& stylesheet,
69   Dali::Application::WINDOW_MODE windowMode,
70   const PositionSize& positionSize,
71   Framework::Type applicationType)
72 {
73   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
74   return application;
75 }
76
77 void Application::PreInitialize( int* argc, char** argv[] )
78 {
79   if( !gPreInitializedApplication )
80   {
81     gPreInitializedApplication = new Application ( argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL );
82
83     gPreInitializedApplication->CreateWindow();    // Only create window
84
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   mSingletonService( SingletonService::New() ),
107   mAdaptorBuilder( nullptr ),
108   mAdaptor( nullptr ),
109   mMainWindow(),
110   mMainWindowMode( windowMode ),
111   mMainWindowName(),
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   mSingletonService.UnregisterAll();
136
137   mMainWindow.Reset();
138   delete mAdaptor;
139   delete mAdaptorBuilder;
140   delete mCommandLineOptions;
141   delete mFramework;
142 }
143
144 void Application::CreateWindow()
145 {
146   if( mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0 )
147   {
148     if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
149     {
150       // Command line options override environment options and full screen
151       mWindowPositionSize.width = mCommandLineOptions->stageWidth;
152       mWindowPositionSize.height = mCommandLineOptions->stageHeight;
153     }
154     else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
155     {
156       // Environment options override full screen functionality if command line arguments not provided
157       mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
158       mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
159     }
160   }
161
162   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
163   mMainWindow = Dali::Window::New( mWindowPositionSize, mMainWindowName, windowClassName, mMainWindowMode == Dali::Application::TRANSPARENT );
164
165   // Quit the application when the window is closed
166   GetImplementation( mMainWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
167 }
168
169 void Application::CreateAdaptor()
170 {
171   DALI_ASSERT_ALWAYS( mMainWindow && "Window required to create adaptor" );
172
173   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
174
175   mAdaptor = Dali::Internal::Adaptor::Adaptor::New( graphicsFactory, mMainWindow, mContextLossConfiguration, &mEnvironmentOptions );
176
177   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
178
179   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
180 }
181
182 void Application::CreateAdaptorBuilder()
183 {
184   mAdaptorBuilder = new AdaptorBuilder();
185 }
186
187 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
188 {
189   mContextLossConfiguration = configuration;
190
191   // Run the application
192   mFramework->Run();
193 }
194
195 void Application::Lower()
196 {
197   // Lower the application without quitting it.
198   mMainWindow.Lower();
199 }
200
201 void Application::Quit()
202 {
203   // Actually quit the application.
204   // Force a call to Quit even if adaptor is not running.
205   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ), false, true );
206 }
207
208 void Application::QuitFromMainLoop()
209 {
210   mAdaptor->Stop();
211
212   mFramework->Quit();
213   // This will trigger OnTerminate(), below, after the main loop has completed.
214 }
215
216 void Application::OnInit()
217 {
218   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
219
220   CreateAdaptorBuilder();
221
222   // If an application was pre-initialized, a window was made in advance
223   if( mLaunchpadState == Launchpad::NONE )
224   {
225     CreateWindow();
226   }
227
228   CreateAdaptor();
229
230   // Run the adaptor
231   mAdaptor->Start();
232
233   // Check if user requires no vsyncing and set Adaptor
234   if (mCommandLineOptions->noVSyncOnRender)
235   {
236     mAdaptor->SetUseHardwareVSync(false);
237   }
238
239   if( ! mStylesheet.empty() )
240   {
241     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
242   }
243
244   // Wire up the LifecycleController
245   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
246
247   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
248   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
249   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
250   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
251   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
252   ResizeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResize );
253   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
254
255   Dali::Application application(this);
256   mInitSignal.Emit( application );
257
258   mAdaptor->NotifySceneCreated();
259 }
260
261 void Application::OnTerminate()
262 {
263   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
264   // delete the window as ecore_x has been destroyed by AppCore
265
266   Dali::Application application(this);
267   mTerminateSignal.Emit( application );
268
269   if( mAdaptor )
270   {
271     // Ensure that the render-thread is not using the surface(window) after we delete it
272     mAdaptor->Stop();
273   }
274
275   mMainWindow.Reset(); // This only resets (clears) the default Window
276 }
277
278 void Application::OnPause()
279 {
280   // A DALi app should handle Pause/Resume events.
281   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
282   // Pausing DALi core only occurs on the Window Hidden framework event
283   Dali::Application application(this);
284   mPauseSignal.Emit( application );
285 }
286
287 void Application::OnResume()
288 {
289   // Emit the signal first so the application can queue any messages before we do an update/render
290   // This ensures we do not just redraw the last frame before pausing if that's not required
291   Dali::Application application(this);
292   mResumeSignal.Emit( application );
293
294   // DALi just delivers the framework Resume event to the application.
295   // Resuming DALi core only occurs on the Window Show framework event
296
297   // Trigger processing of events queued up while paused
298   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation( GetAdaptor() );
299   coreEventInterface.ProcessCoreEvents();
300 }
301
302 void Application::OnReset()
303 {
304   /*
305    * usually, reset callback was called when a caller request to launch this application via aul.
306    * because Application class already handled initialization in OnInit(), OnReset do nothing.
307    */
308   Dali::Application application(this);
309   mResetSignal.Emit( application );
310 }
311
312 void Application::OnAppControl(void *data)
313 {
314   Dali::Application application(this);
315   mAppControlSignal.Emit( application , data );
316 }
317
318 void Application::OnLanguageChanged()
319 {
320   mAdaptor->NotifyLanguageChanged();
321   Dali::Application application(this);
322   mLanguageChangedSignal.Emit( application );
323 }
324
325 void Application::OnRegionChanged()
326 {
327   Dali::Application application(this);
328   mRegionChangedSignal.Emit( application );
329 }
330
331 void Application::OnBatteryLow( Dali::DeviceStatus::Battery::Status status )
332 {
333   Dali::Application application(this);
334   mBatteryLowSignal.Emit( application );
335
336   mLowBatterySignal.Emit( status );
337 }
338
339 void Application::OnMemoryLow( Dali::DeviceStatus::Memory::Status status )
340 {
341   Dali::Application application(this);
342   mMemoryLowSignal.Emit( application );
343
344   mLowMemorySignal.Emit( status );
345 }
346 void Application::OnResize(Dali::Adaptor& adaptor)
347 {
348   Dali::Application application(this);
349   mResizeSignal.Emit( application );
350 }
351
352 bool Application::AddIdle( CallbackBase* callback, bool hasReturnValue )
353 {
354   return mAdaptor->AddIdle( callback, hasReturnValue );
355 }
356
357 std::string Application::GetRegion() const
358 {
359   return mFramework->GetRegion();
360 }
361
362 std::string Application::GetLanguage() const
363 {
364   return mFramework->GetLanguage();
365 }
366
367 Dali::Adaptor& Application::GetAdaptor()
368 {
369   return *mAdaptor;
370 }
371
372 Dali::Window Application::GetWindow()
373 {
374   return mMainWindow;
375 }
376
377 // Stereoscopy
378
379 void Application::SetViewMode( ViewMode viewMode )
380 {
381   mViewMode = viewMode;
382 }
383
384 ViewMode Application::GetViewMode() const
385 {
386   return mViewMode;
387 }
388
389 void Application::SetStereoBase( float stereoBase )
390 {
391   mStereoBase = stereoBase;
392 }
393
394 float Application::GetStereoBase() const
395 {
396   return mStereoBase;
397 }
398
399 void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
400 {
401   Any surface;
402   auto renderSurfaceFactory = Dali::Internal::Adaptor::GetRenderSurfaceFactory();
403   std::unique_ptr<Internal::Adaptor::WindowRenderSurface> renderSurface =
404       renderSurfaceFactory->CreateWindowRenderSurface( positionSize, surface, false );
405
406   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).ReplaceSurface( mMainWindow, *renderSurface.release() );
407   mWindowPositionSize = positionSize;
408 }
409
410 std::string Application::GetResourcePath()
411 {
412   return Internal::Adaptor::Framework::GetResourcePath();
413 }
414
415 std::string Application::GetDataPath()
416 {
417   return Internal::Adaptor::Framework::GetDataPath();
418 }
419
420 void Application::SetStyleSheet( const std::string& stylesheet )
421 {
422   mStylesheet = stylesheet;
423 }
424
425 ApplicationPtr Application::GetPreInitializedApplication()
426 {
427   return gPreInitializedApplication;
428 }
429
430 } // namespace Adaptor
431
432 } // namespace Internal
433
434 } // namespace Dali