40b16d9ec3ab9064c41cc02c7e28a555f3a7437c
[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/accessibility.h>
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/system/common/singleton-service-impl.h>
32 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
33 #include <dali/internal/window-system/common/window-impl.h>
34 #include <dali/internal/window-system/common/window-render-surface.h>
35 #include <dali/internal/window-system/common/render-surface-factory.h>
36
37 // To disable a macro with the same name from one of OpenGL headers
38 #undef Status
39
40 namespace Dali
41 {
42
43 namespace TizenPlatform
44 {
45 class TizenPlatformAbstraction;
46 }
47
48 namespace Integration
49 {
50 class Core;
51 }
52
53 namespace Internal
54 {
55
56 namespace Adaptor
57 {
58
59 namespace
60 {
61
62 const float DEFAULT_STEREO_BASE( 65.0f );
63
64 } // unnamed namespace
65
66 ApplicationPtr Application::gPreInitializedApplication( NULL );
67
68 ApplicationPtr Application::New(
69   int* argc,
70   char **argv[],
71   const std::string& stylesheet,
72   Dali::Application::WINDOW_MODE windowMode,
73   const PositionSize& positionSize,
74   Framework::Type applicationType)
75 {
76   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
77   return application;
78 }
79
80 void Application::PreInitialize( int* argc, char** argv[] )
81 {
82   if( !gPreInitializedApplication )
83   {
84     gPreInitializedApplication = new Application ( argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL );
85
86     gPreInitializedApplication->CreateWindow();    // Only create window
87
88     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
89
90     //Make DefaultFontDescription cached
91     Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
92     Dali::TextAbstraction::FontDescription defaultFontDescription;
93     fontClient.GetDefaultPlatformFontDescription( defaultFontDescription );
94   }
95 }
96
97 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
98   Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType )
99 : mInitSignal(),
100   mTerminateSignal(),
101   mPauseSignal(),
102   mResumeSignal(),
103   mResetSignal(),
104   mResizeSignal(),
105   mAppControlSignal(),
106   mLanguageChangedSignal(),
107   mRegionChangedSignal(),
108   mBatteryLowSignal(),
109   mMemoryLowSignal(),
110   mEventLoop( nullptr ),
111   mFramework( nullptr ),
112   mContextLossConfiguration( Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS ),
113   mCommandLineOptions( nullptr ),
114   mSingletonService( SingletonService::New() ),
115   mAdaptorBuilder( nullptr ),
116   mAdaptor( nullptr ),
117   mMainWindow(),
118   mMainWindowMode( windowMode ),
119   mMainWindowName(),
120   mMainWindowReplaced( false ),
121   mStylesheet( stylesheet ),
122   mEnvironmentOptions(),
123   mWindowPositionSize( positionSize ),
124   mLaunchpadState( Launchpad::NONE ),
125   mSlotDelegate( this ),
126   mViewMode( MONO ),
127   mStereoBase( DEFAULT_STEREO_BASE )
128 {
129   // Get mName from environment options
130   mMainWindowName = mEnvironmentOptions.GetWindowName();
131   if( mMainWindowName.empty() && argc && ( *argc > 0 ) )
132   {
133     // Set mName from command-line args if environment option not set
134     mMainWindowName = (*argv)[0];
135   }
136
137   mCommandLineOptions = new CommandLineOptions(argc, argv);
138   mFramework = new Framework( *this, argc, argv, applicationType );
139   mUseRemoteSurface = (applicationType == Framework::WATCH);
140 }
141
142 Application::~Application()
143 {
144   mSingletonService.UnregisterAll();
145
146   mMainWindow.Reset();
147   delete mAdaptor;
148   delete mAdaptorBuilder;
149   delete mCommandLineOptions;
150   delete mFramework;
151 }
152
153 void Application::CreateWindow()
154 {
155   if( mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0 )
156   {
157     if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
158     {
159       // Command line options override environment options and full screen
160       mWindowPositionSize.width = mCommandLineOptions->stageWidth;
161       mWindowPositionSize.height = mCommandLineOptions->stageHeight;
162     }
163     else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
164     {
165       // Environment options override full screen functionality if command line arguments not provided
166       mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
167       mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
168     }
169   }
170
171   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
172
173   Internal::Adaptor::Window* window = Internal::Adaptor::Window::New( mWindowPositionSize, mMainWindowName, windowClassName, mMainWindowMode == Dali::Application::TRANSPARENT );
174   mMainWindow = Dali::Window( window );
175
176   // Quit the application when the window is closed
177   GetImplementation( mMainWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
178 }
179
180 void Application::CreateAdaptor()
181 {
182   DALI_ASSERT_ALWAYS( mMainWindow && "Window required to create adaptor" );
183
184   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
185
186   Integration::SceneHolder sceneHolder = Integration::SceneHolder( &Dali::GetImplementation( mMainWindow ) );
187
188   mAdaptor = Adaptor::New( graphicsFactory, sceneHolder, mContextLossConfiguration, &mEnvironmentOptions );
189
190   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
191
192   Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
193 }
194
195 void Application::CreateAdaptorBuilder()
196 {
197   mAdaptorBuilder = new AdaptorBuilder();
198 }
199
200 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
201 {
202   mContextLossConfiguration = configuration;
203
204   // Run the application
205   mFramework->Run();
206 }
207
208 void Application::Lower()
209 {
210   // Lower the application without quitting it.
211   mMainWindow.Lower();
212 }
213
214 void Application::Quit()
215 {
216   // Actually quit the application.
217   // Force a call to Quit even if adaptor is not running.
218   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ), false, true );
219 }
220
221 void Application::QuitFromMainLoop()
222 {
223   Accessibility::Bridge::GetCurrentBridge()->Terminate();
224
225   mAdaptor->Stop();
226
227   mFramework->Quit();
228   // This will trigger OnTerminate(), below, after the main loop has completed.
229 }
230
231 void Application::OnInit()
232 {
233   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
234
235   CreateAdaptorBuilder();
236
237   // If an application was pre-initialized, a window was made in advance
238   if( mLaunchpadState == Launchpad::NONE )
239   {
240     CreateWindow();
241   }
242
243   CreateAdaptor();
244
245   // Run the adaptor
246   mAdaptor->Start();
247
248   if( ! mStylesheet.empty() )
249   {
250     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
251   }
252
253   // Wire up the LifecycleController
254   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
255
256   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
257   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
258   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
259   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
260   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
261   ResizeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResize );
262   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
263
264   Dali::Application application(this);
265   mInitSignal.Emit( application );
266
267   mAdaptor->NotifySceneCreated();
268 }
269
270 void Application::OnTerminate()
271 {
272   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
273   // delete the window as ecore_x has been destroyed by AppCore
274
275   Dali::Application application(this);
276   mTerminateSignal.Emit( application );
277
278   if( mAdaptor )
279   {
280     // Ensure that the render-thread is not using the surface(window) after we delete it
281     mAdaptor->Stop();
282   }
283
284   mMainWindow.Reset(); // This only resets (clears) the default Window
285 }
286
287 void Application::OnPause()
288 {
289   // A DALi app should handle Pause/Resume events.
290   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
291   // Pausing DALi core only occurs on the Window Hidden framework event
292   Dali::Application application(this);
293   mPauseSignal.Emit( application );
294 }
295
296 void Application::OnResume()
297 {
298   // Emit the signal first so the application can queue any messages before we do an update/render
299   // This ensures we do not just redraw the last frame before pausing if that's not required
300   Dali::Application application(this);
301   mResumeSignal.Emit( application );
302
303   // DALi just delivers the framework Resume event to the application.
304   // Resuming DALi core only occurs on the Window Show framework event
305
306   // Trigger processing of events queued up while paused
307   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation( GetAdaptor() );
308   coreEventInterface.ProcessCoreEvents();
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   mAdaptor->NotifyLanguageChanged();
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( Dali::DeviceStatus::Battery::Status status )
341 {
342   Dali::Application application(this);
343   mBatteryLowSignal.Emit( application );
344
345   mLowBatterySignal.Emit( status );
346 }
347
348 void Application::OnMemoryLow( Dali::DeviceStatus::Memory::Status status )
349 {
350   Dali::Application application(this);
351   mMemoryLowSignal.Emit( application );
352
353   mLowMemorySignal.Emit( status );
354 }
355
356 void Application::OnResize(Dali::Adaptor& adaptor)
357 {
358   Dali::Application application(this);
359   mResizeSignal.Emit( application );
360 }
361
362 bool Application::AddIdle( CallbackBase* callback, bool hasReturnValue )
363 {
364   return mAdaptor->AddIdle( callback, hasReturnValue );
365 }
366
367 std::string Application::GetRegion() const
368 {
369   return mFramework->GetRegion();
370 }
371
372 std::string Application::GetLanguage() const
373 {
374   return mFramework->GetLanguage();
375 }
376
377 Dali::Adaptor& Application::GetAdaptor()
378 {
379   return *mAdaptor;
380 }
381
382 Dali::Window Application::GetWindow()
383 {
384   // Changed to return a different window handle after ReplaceWindow is called
385   // just for backward compatibility to make the test case pass
386   if ( mMainWindowReplaced )
387   {
388     Internal::Adaptor::Window* window = Internal::Adaptor::Window::New( PositionSize(), "ReplacedWindow", "", false );
389     return Dali::Window( window );
390   }
391   else
392   {
393     return mMainWindow;
394   }
395 }
396
397 // Stereoscopy
398
399 void Application::SetViewMode( ViewMode viewMode )
400 {
401   mViewMode = viewMode;
402 }
403
404 ViewMode Application::GetViewMode() const
405 {
406   return mViewMode;
407 }
408
409 void Application::SetStereoBase( float stereoBase )
410 {
411   mStereoBase = stereoBase;
412 }
413
414 float Application::GetStereoBase() const
415 {
416   return mStereoBase;
417 }
418
419 void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
420 {
421   // This API is kept just for backward compatibility to make the test case pass.
422
423   mMainWindowReplaced = true;
424   OnResize( *mAdaptor );
425 }
426
427 std::string Application::GetResourcePath()
428 {
429   return Internal::Adaptor::Framework::GetResourcePath();
430 }
431
432 std::string Application::GetDataPath()
433 {
434   return Internal::Adaptor::Framework::GetDataPath();
435 }
436
437 void Application::SetStyleSheet( const std::string& stylesheet )
438 {
439   mStylesheet = stylesheet;
440 }
441
442 void Application::SetCommandLineOptions( int* argc, char **argv[] )
443 {
444   delete mCommandLineOptions;
445
446   mCommandLineOptions = new CommandLineOptions( argc, argv );
447
448   mFramework->SetCommandLineOptions( argc, argv );
449 }
450
451 ApplicationPtr Application::GetPreInitializedApplication()
452 {
453   return gPreInitializedApplication;
454 }
455
456 } // namespace Adaptor
457
458 } // namespace Internal
459
460 } // namespace Dali